{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1.HTML5\n",
    "\n",
    "上节回顾：<a href=\"https://www.cnblogs.com/dotnetcrazy/p/10061671.html\" target=\"_blank\">一文读懂ES6（附PY3对比）</a> | <a href=\"https://www.cnblogs.com/dotnetcrazy/p/10118756.html\" target=\"_blank\">一文入门NodeJS</a>\n",
    "\n",
    "演示demo：<https://github.com/lotapp/BaseCode/tree/master/javascript/0.H5_C3/H5>\n",
    "\n",
    "参考文档：<https://www.w3cschool.cn/html5> | <https://developer.mozilla.org/zh-CN/docs/Web/Guide/HTML/HTML5>\n",
    "\n",
    "HTML5主要目的是为了在移动设备上支持多媒体，eg：`<video>`、`<audio>`、`<canvas>`（PS：Flash太重量级）\n",
    "\n",
    "这么多年下来了，有些API被广泛支持，有些API逐渐淡化在视线中了（eg：`WebSQL`、`IndexedDB`等）\n",
    "\n",
    "我们来看下`常用`的新特性：\n",
    "1. 取消了过时的一些显示效果标记，eg：`<font>`、`<center>`\n",
    "    - PS：用CSS实现\n",
    "2. 新表单元素引入\n",
    "    - eg：input新的type：`number`、`url`、`email`...\n",
    "3. 新语义标签的引入\n",
    "    - eg：`<nav>`、`<header>`、`<footer>`...\n",
    "4. 多媒体以及图形方面的扩展\n",
    "    - eg：`<canvas>`、`<video>`、`<audio>`\n",
    "5. web本地存储\n",
    "    - eg：`localStorage`\n",
    "6. 一些HTML5提供的API\n",
    "\n",
    "优点：**跨平台**\n",
    "\n",
    "PC端支持不是特别友好\n",
    "    - PS：主要是低版本浏览器不太支持新特性\n",
    "\n",
    "## 1.1.语义标签\n",
    "\n",
    "有利于SEO，有利于盲人阅读等，官方文档：<http://www.w3school.com.cn/html/html5_semantic_elements.asp>\n",
    "> <https://developer.mozilla.org/zh-CN/docs/Web/Guide/HTML/Sections_and_Outlines_of_an_HTML5_document>\n",
    "\n",
    "### 1.1.1.基础\n",
    "\n",
    "常用语义化标签：\n",
    "```html\n",
    "<nav>导航区域</nav>\n",
    "\n",
    "<header>头部区域</header>\n",
    "\n",
    "<main>主内容区</main>\n",
    "\n",
    "<footer>尾部区域</footer>\n",
    "\n",
    "<article>文章区域</article>\n",
    "\n",
    "<aside>侧栏区域</aside>\n",
    "\n",
    "<section>内容组/节</section>\n",
    "```\n",
    "\n",
    "PS：可以将网站首页划分为简介、内容、联系信息等内容组（`section`）\n",
    "\n",
    "官方给的语义化标签：\n",
    "```html\n",
    "标签\t\t\t\t描述\n",
    "<article>\t   定义文章。\n",
    "<aside>\t     定义页面内容以外的内容。\n",
    "<details>\t   定义用户能够查看或隐藏的额外细节。\n",
    "<figcaption>\t定义 <figure> 元素的标题。\n",
    "<figure>\t    规定自包含内容，比如图示、图表、照片、代码清单等。\n",
    "<footer>\t\t定义文档或节的页脚。\n",
    "<header>\t\t规定文档或节的页眉。\n",
    "<main>\t\t  规定文档的主内容。\n",
    "<mark>\t\t  定义重要的或强调的文本。\n",
    "<nav>\t\t   定义导航链接。\n",
    "<section>\t   定义文档中的节。\n",
    "<summary>\t   定义 <details> 元素的可见标题。\n",
    "<time>\t\t  定义日期/时间。\n",
    "```\n",
    "\n",
    "PS：**`<div>没有语义的标签</div>`，使用方面和语义标签一样，但SEO效果没语义标签好**\n",
    "\n",
    "#### 效果图\n",
    "\n",
    "可以看看我几年前写的文章：<http://www.cnblogs.com/dunitian/p/5123741.html>\n",
    "\n",
    "### 1.1.2.兼容\n",
    "\n",
    "先看看最关心的兼容性问题：\n",
    "\n",
    "低版本会把语义标签当成用户自定义的标签，eg：\n",
    "```html\n",
    "<!DOCTYPE html>\n",
    "<html>\n",
    "<head>\n",
    "    <meta charset=\"utf-8\">\n",
    "    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n",
    "    <title>Page Title</title>\n",
    "    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n",
    "    <style>\n",
    "        nav {\n",
    "            height: 200px;\n",
    "            background-color: red;\n",
    "        }\n",
    "\n",
    "        div {\n",
    "            height: 200px;\n",
    "            background-color: blue;\n",
    "        }\n",
    "    </style>\n",
    "</head>\n",
    "<body>\n",
    "    <!-- 导航 -->\n",
    "    <nav>语义标签的导航</nav>\n",
    "    <div>没有语义的导航</div>\n",
    "</body>\n",
    "</html>\n",
    "```\n",
    "浏览器基本上都是支持的\n",
    "![1.支持.png](https://img2018.cnblogs.com/blog/1127869/201903/1127869-20190316134604482-331758714.png)\n",
    "\n",
    "但是低版本不能识别（eg：`IE8`）\n",
    "![1.低版本.png](https://img2018.cnblogs.com/blog/1127869/201903/1127869-20190316134424380-552616009.png)\n",
    "\n",
    "### 1.1.3.解决\n",
    "\n",
    "现在基本上都是引用一下兼容的库，我们先看看本质是啥：\n",
    "```html\n",
    "<!DOCTYPE html>\n",
    "<html>\n",
    "\n",
    "<head>\n",
    "    <meta charset=\"utf-8\">\n",
    "    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n",
    "    <title>Page Title</title>\n",
    "    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n",
    "    <style>\n",
    "        nav {\n",
    "            height: 200px;\n",
    "            background-color: red;\n",
    "            /* ie创建自定义标签默认是行级元素，height不生效，所以需要设置block */\n",
    "            display: block;\n",
    "        }\n",
    "\n",
    "        div {\n",
    "            height: 200px;\n",
    "            background-color: blue;\n",
    "        }\n",
    "    </style>\n",
    "    <script>\n",
    "        // 创建自定义标签\n",
    "        document.createElement(\"nav\")\n",
    "    </script>\n",
    "</head>\n",
    "\n",
    "<body>\n",
    "    <!-- 本质就是因为不能识别，那就创建自定义标签，ie默认创建的为行级标签，那就设置为块级元素 -->\n",
    "    <nav>语义标签的导航</nav>\n",
    "    <div>没有语义的导航</div>\n",
    "</body>\n",
    "\n",
    "</html>\n",
    "```\n",
    "兼容解决：\n",
    "![1.解决.png](https://img2018.cnblogs.com/blog/1127869/201903/1127869-20190316134442208-581386402.png)\n",
    "\n",
    "**PS：本质就是因为不能识别这些语义化标签，那就需要创建自定义的标签。而ie默认创建的标签为行级标签，height就不生效了，所以就需要设置为块级元素**\n",
    "\n",
    "### 兼容方案\n",
    "\n",
    "**推荐一个兼容旧版本语义标签的库：<https://github.com/aFarkas/html5shiv>**\n",
    "\n",
    "```html\n",
    "<!DOCTYPE html>\n",
    "<html>\n",
    "\n",
    "<head>\n",
    "    <meta charset=\"utf-8\">\n",
    "    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n",
    "    <title>Page Title</title>\n",
    "    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n",
    "    <style>\n",
    "        nav {\n",
    "            height: 200px;\n",
    "            background-color: red;\n",
    "            display: block;\n",
    "        }\n",
    "\n",
    "        div {\n",
    "            height: 200px;\n",
    "            background-color: blue;\n",
    "        }\n",
    "    </style>\n",
    "    <!-- if lt IE 9：低于`IE9`版本会加载 -->\n",
    "    <!--[if lt IE 9]>\n",
    "        <script type=\"text/javascript\" src=\"../js/html5shiv.min.js\"></script>\n",
    "    <![endif]-->\n",
    "</head>\n",
    "\n",
    "<body>\n",
    "    <nav>语义标签的导航</nav>\n",
    "    <div>没有语义的导航</div>\n",
    "</body>\n",
    "\n",
    "</html>\n",
    "```\n",
    "\n",
    "PS：小知识点\n",
    "- **`[if IE]`**：`IE`浏览器\n",
    "- **`[if !IE]`**：不是`IE`浏览器\n",
    "- **`[if lt IE 9]`**：低于`IE9`\n",
    "- **`[if lte IE 8]`**：`<=IE8`\n",
    "\n",
    "**PS：我们一般使用`Modernizr`即可**（默认包含了`html5shiv`）\n",
    "> 还可以解决其他兼容性问题\n",
    "\n",
    "```javascript\n",
    "<!--[if lte IE 9]>\n",
    "     <script type=\"text/javascript\" src=\"https://cdn.staticfile.org/modernizr/2.8.3/modernizr.min.js\"></script>\n",
    "<![endif]-->\n",
    "```\n",
    "\n",
    "来个语义化的页面演示：<https://github.lesschina.com/html5/>\n",
    "> PS：目前只适配了iPad、PC和IE9以上浏览器（移动端为了帮大家省流量准备单独搞个页面）\n",
    "\n",
    "先看效果：（我开源了，感兴趣的可以去Fork）\n",
    "> PS：主打宽屏（逆天是1920的宽屏）\n",
    "\n",
    "![PC效果图.jpg](https://img2018.cnblogs.com/blog/1127869/201904/1127869-20190416090911703-56471476.jpg)\n",
    "\n",
    "大致框架：<https://github.com/lotapp/H5Blog>\n",
    "```html\n",
    "<header>\n",
    "  <div class=\"logo\"></div>\n",
    "  <!-- nav>ul>li*5>a:link -->\n",
    "  <nav>\n",
    "    <ul>\n",
    "      <li><a href=\"#\">首页</a></li>\n",
    "      <li><a href=\"#\">资讯</a></li>\n",
    "      <li><a href=\"#\">专业</a></li>\n",
    "      <li><a href=\"#\">生活</a></li>\n",
    "      <li><a href=\"#\">国学</a></li>\n",
    "      <li><a href=\"#\">资源</a></li>\n",
    "      <li><a href=\"#\">实验</a></li>\n",
    "    </ul>\n",
    "  </nav>\n",
    "  <div class=\"search\"></div>\n",
    "</header>\n",
    "<div class=\"banner\">\n",
    "  <!-- ul>li*5 -->\n",
    "  <ul>\n",
    "    <li></li>\n",
    "    <li></li>\n",
    "    <li></li>\n",
    "    <li></li>\n",
    "    <li></li>\n",
    "  </ul>\n",
    "</div>\n",
    "<!-- 主体内容 -->\n",
    "<main>\n",
    "  <!-- 文章部分 -->\n",
    "  <article>\n",
    "    <!-- 最新文章 -->\n",
    "    <section class=\"new_article\">\n",
    "      <header>\n",
    "        <nav>\n",
    "          <ul>\n",
    "            <li>首页</li>\n",
    "            <li>资讯</li>\n",
    "            <li>专业</li>\n",
    "            <li>生活</li>\n",
    "            <li>国学</li>\n",
    "            <li>资源</li>\n",
    "          </ul>\n",
    "        </nav>\n",
    "      </header>\n",
    "      <!-- 对应菜单的内容 -->\n",
    "      <div class=\"new_tabs\">\n",
    "        <!-- div.new_item*5 -->\n",
    "        <div class=\"new_item\">内容</div>\n",
    "        <div class=\"new_item\">内容</div>\n",
    "        <div class=\"new_item\">内容</div>\n",
    "        <div class=\"new_item\">内容</div>\n",
    "        <div class=\"new_item\">内容</div>\n",
    "      </div>\n",
    "    </section>\n",
    "    <!-- 文章列表 -->\n",
    "    <section class=\"blog_lsit\">\n",
    "      <h2>推荐文章</h2>\n",
    "      <!-- ul>li*15 -->\n",
    "      <ul>\n",
    "        <li></li>\n",
    "        <li></li>\n",
    "        <li></li>\n",
    "        <li></li>\n",
    "        <li></li>\n",
    "      </ul>\n",
    "    </section>\n",
    "    <!-- 分页栏 -->\n",
    "    <footer>\n",
    "      <!-- ul>li*5（也可以直接使用a标签） -->\n",
    "      <ul>\n",
    "        <li></li>\n",
    "        <li></li>\n",
    "        <li></li>\n",
    "        <li></li>\n",
    "        <li></li>\n",
    "      </ul>\n",
    "    </footer>\n",
    "  </article>\n",
    "  <!-- 侧边栏，相关文章 -->\n",
    "  <!-- aside>sestion*5>h2+div -->\n",
    "  <aside>\n",
    "    <sestion>\n",
    "      <h2></h2>\n",
    "      <div></div>\n",
    "    </sestion>\n",
    "    <sestion>\n",
    "      <h2></h2>\n",
    "      <div></div>\n",
    "    </sestion>\n",
    "  </aside>\n",
    "</main>\n",
    "<!-- 尾部信息 -->\n",
    "<footer>\n",
    "<address>xxx</address>\n",
    "</footer>\n",
    "```\n",
    "\n",
    "## 1.2.多媒体标签\n",
    "\n",
    "### video and audio\n",
    "\n",
    "官方文档：<http://www.w3school.com.cn/html5/html_5_audio.asp> and <http://www.w3school.com.cn/html5/html_5_video.asp>\n",
    "\n",
    "主要属性：\n",
    "1. **controls：显示控件**\n",
    "2. **muted：静音**\n",
    "3. autoplay：自动播放\n",
    "4. loop：循环播放\n",
    "5. _preload：预加载_\n",
    "\n",
    "```html\n",
    "<video src=\"http://www.w3school.com.cn/i/movie.mp4\" controls autoplay loop muted>您的浏览器不支持video标签</video>\n",
    "<audio src=\"http://www.w3school.com.cn/i/song.mp3\" controls autoplay loop muted>您的浏览器不支持</audio>\n",
    "```\n",
    "**PS：大家有没有发现，现在视频网站都是自动播放，很多默认都是静音？**\n",
    "\n",
    "但是需要注意下不同浏览器的兼容格式：\n",
    "![2.视频格式.png](https://img2018.cnblogs.com/blog/1127869/201903/1127869-20190316143440668-433004294.png)\n",
    "![2.音频格式.png](https://img2018.cnblogs.com/blog/1127869/201903/1127869-20190316143901996-1794955847.png)\n",
    "\n",
    "上面代码的兼容写法如下：\n",
    "```html\n",
    "<video controls>\n",
    "    <source src=\"http://www.w3school.com.cn/i/movie.mp4\">\n",
    "    <source src=\"http://www.w3school.com.cn/i/movie.ogg\">\n",
    "    您的浏览器不支持video标签\n",
    "</video>\n",
    "\n",
    "<audio controls>\n",
    "    <source src=\"http://www.w3school.com.cn/i/song.mp3\">\n",
    "    <source src=\"http://www.w3school.com.cn/i/song.ogg\">\n",
    "    您的浏览器不支持audio标签\n",
    "</audio>\n",
    "```\n",
    "\n",
    "### 扩展\n",
    "\n",
    "这个部分几年前讲过，记得还做了个播放器，就不去讲了，项目里也基本上用大厂开源的库：\n",
    ">PS：这几款播放器用的挺多：（推荐加粗项目）\n",
    "\n",
    "1. **`Video.js`（开源`2.45W+`）**\n",
    "    - URL：<https://github.com/videojs/video.js>\n",
    "    - Vue版：<https://github.com/surmon-china/vue-video-player>\n",
    "2. **`cyberplayer`（百度）**\n",
    "    - PS：基于`video.js`\n",
    "    - URL：<https://cloud.baidu.com/doc/MCT/Web-SDK.html>\n",
    "3. **`tencentplayer`（腾讯）**\n",
    "    - URL：<http://v.qq.com/open/qna.html>\n",
    "4. `webtorrent`(开源`1.9w+`)\n",
    "    - URL：<https://github.com/webtorrent/webtorrent>\n",
    "5. `Flv.js`（Bilibili开源`1.4w+`）\n",
    "    - URL：<https://github.com/Bilibili/flv.js>\n",
    "6. `DPlayer`（开源`5.3k+`）\n",
    "    - URL：<https://github.com/MoePlayer/DPlayer>\n",
    "7. `jwplayer`（开源`1.8k+`）\n",
    "    - URL：<https://github.com/jwplayer/jwplayer>\n",
    "8. **Chimee组件化框架（开源`1.65k+`）**\n",
    "    - URL：<https://github.com/Chimeejs/chimee>\n",
    "9. `youkuplayer`（优酷）\n",
    "    - URL：<http://cloud.youku.com/tools>\n",
    "\n",
    "---\n",
    "\n",
    "## 1.3.新表单元素\n",
    "\n",
    "### 1.3.1.智能表单类型\n",
    "\n",
    "1. **`email`：合法邮箱**\n",
    "2. **`url`：合法url地址**\n",
    "3. **`number`：合法数字**\n",
    "4. `date`：显示日期\n",
    "5. `month`：显示月份\n",
    "6. `week`：显示第几周\n",
    "7. `time`：显示时间\n",
    "8. `range`：滑动条\n",
    "9. `search`：搜索框\n",
    "10. _`color`：拾色器_\n",
    "\n",
    "使用`setCustomValidity()`设置自定义验证\n",
    "\n",
    "### 1.3.2.表单属性\n",
    "\n",
    "#### 1.form属性\n",
    "\n",
    "1. **`autocomplete=\"on|off\"`：是否自动完成**\n",
    "2. `novalidate=\"true|false\"`：不校验|校验数据\n",
    "\n",
    "#### 2.input属性\n",
    "\n",
    "1. **`required`：必填选项**\n",
    "2. **`autofocus`：自动获取焦点**\n",
    "3. **`placeholder`：提示信息**\n",
    "4. **`maxlength`：最大字符数**\n",
    "5. **`autocomplete`：取消候选词**\n",
    "    - PS：一般都是自己设置，如果不关闭会重叠（百度代码：`<input value=\"\" maxlength=\"255\" autocomplete=\"off\">`）\n",
    "6. `multiple`：多选效果\n",
    "7. _`form=\"表单id`：把不在表单域里面的input添加到表单中_\n",
    "\n",
    "```html\n",
    "<select multiple>\n",
    "    <option>11</option>\n",
    "    <option>22</option>\n",
    "    <option>33</option>\n",
    "    <option>44</option>\n",
    "</select>\n",
    "\n",
    "<input type=\"text\" list=\"list_id\" />\n",
    "<datalist id=\"list_id\">\n",
    "    <option>11</option>\n",
    "    <option>22</option>\n",
    "</datalist>\n",
    "```\n",
    "\n",
    "### 1.3.3.扩展说明\n",
    "\n",
    "这个之前也说的很详细了，这边列了常用属性就完事了，感兴趣可以去老文章看看：<https://www.cnblogs.com/dunitian/p/5125371.html>\n",
    "> **PS：有些是真方便，但表单验证一般不太用（不同浏览器表现UI不同，产品经理会打你的哦~）**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1.4.常用API\n",
    "\n",
    "### 1.4.1.Dom相关API（必看）\n",
    "\n",
    "这个高版本IE都支持，而且出了dom相关API后，现在基本上不太用JQ了\n",
    "> PS：有些项目需要兼容老版本浏览器的另说\n",
    "\n",
    "#### 1.获取页面元素\n",
    "\n",
    "**`获取页面元素`**：\n",
    "1. `document.querySelector(\"选择器\")`：返回符合选择器的第一个元素\n",
    "2. `document.querySelectorAll(\"选择器\")`：返回所有符合选择器的元素\n",
    "3. PS：选择器可以是CSS中的任意一种（你CSS怎么写的，这边就怎么写）\n",
    "    - eg：`document.querySelector(\"#id\")`、`document.querySelector(\".class\")`、`document.querySelector(\"tag\")`\n",
    "\n",
    "举个栗子：**我想让Python变成红色，用CSS可以这么写**：\n",
    "```html\n",
    "<!DOCTYPE html>\n",
    "<html>\n",
    "<head>\n",
    "    <meta charset=\"utf-8\">\n",
    "    <title>选择器</title>\n",
    "    <style>\n",
    "        li span {\n",
    "          color: red;\n",
    "        }\n",
    "    </style>\n",
    "</head>\n",
    "<body>\n",
    "   <ul>\n",
    "     <li><span>Python</span></li>\n",
    "     <li>JavaScript</li>\n",
    "   </ul>\n",
    "</body>\n",
    "</html>\n",
    "```\n",
    "效果：\n",
    "![3.1.one.png](https://img2018.cnblogs.com/blog/1127869/201903/1127869-20190324091025087-1481988082.png)\n",
    "\n",
    "**通过API可以这么干**：（选择器写法和CSS一样）\n",
    "```html\n",
    "<!DOCTYPE html>\n",
    "<html>\n",
    "<head>\n",
    "    <meta charset=\"utf-8\">\n",
    "    <title>选择器</title>\n",
    "</head>\n",
    "<body>\n",
    "  <ul>\n",
    "    <li><span>Python</span></li>\n",
    "    <li>JavaScript</li>\n",
    "  </ul>\n",
    "  <script>\n",
    "    // 只能选中第一个元素（单个）\n",
    "    document.querySelector(\"li span\").style.color = \"red\";\n",
    "  </script>\n",
    "</body>\n",
    "</html>\n",
    "```\n",
    "\n",
    "**全部变成红色可以这么干**：\n",
    "```html\n",
    "<!DOCTYPE html>\n",
    "<html>\n",
    "<head>\n",
    "    <meta charset=\"utf-8\">\n",
    "    <title>选择器</title>\n",
    "</head>\n",
    "<body>\n",
    "  <ul>\n",
    "    <li><span>Python</span></li>\n",
    "    <li>JavaScript</li>\n",
    "  </ul>\n",
    "  <script>\n",
    "    // 选中所有符合的元素（列表）\n",
    "    dom_list = document.querySelectorAll(\"li\");\n",
    "    // 用法很像C#\n",
    "    dom_list.forEach(item => {\n",
    "        item.style.color = \"red\";\n",
    "     });\n",
    "  </script>\n",
    "</body>\n",
    "</html>\n",
    "```\n",
    "效果：\n",
    "![3.1.all.png](https://img2018.cnblogs.com/blog/1127869/201903/1127869-20190324090835319-659564546.png)\n",
    "\n",
    "#### 2.类名操作\n",
    "\n",
    "**`类名操作`**（页面元素对象的方法）\n",
    "1. `xxdom.classList.add(\"类名\")`：给当前dom元素添加类样式\n",
    "2. `dom.classList.remove(\"类名\")`：移除当前dom元素的类样式\n",
    "3. `dom.classList.contains(\"类名\")`：检测是否包含类样式\n",
    "4. `dom.classList.toggle(\"类名\")`：切换类样式\n",
    "    - PS：有就删除，没有就添加\n",
    "\n",
    "举个栗子：\n",
    "```html\n",
    "<!DOCTYPE html>\n",
    "<html>\n",
    "<head>\n",
    "    <meta charset=\"utf-8\">\n",
    "    <title>类名操作</title>\n",
    "    <style type=\"text/css\">\n",
    "        .dis {\n",
    "          background-color: red;\n",
    "          width: 300px;\n",
    "          height: 50px;\n",
    "        }\n",
    "    </style>\n",
    "</head>\n",
    "<body>\n",
    "    <div class=\"demo\"></div>\n",
    "    <div>\n",
    "        <input type=\"button\" value=\"添加类名\" class=\"add mmd\">\n",
    "        <input type=\"button\" value=\"移除类名\" class=\"remove\">\n",
    "        <input type=\"button\" value=\"切换类名\" class=\"toggle\">\n",
    "        <input type=\"button\" value=\"是否包含类名\" class=\"contains\">\n",
    "    </div>\n",
    "    <script>\n",
    "        // 演示对象\n",
    "        let demo_obj = document.querySelector(\".demo\");\n",
    "\n",
    "        // 给几个按钮对象注册点击事件\n",
    "        // 添加\n",
    "        document.querySelector(\".add\").onclick = () => {\n",
    "            demo_obj.classList.add(\"dis\");\n",
    "        };\n",
    "        // 移除\n",
    "        let remove_btn = document.querySelector(\".remove\").onclick = () => {\n",
    "            demo_obj.classList.remove(\"dis\");\n",
    "        };\n",
    "        // 切换\n",
    "        let toggle_btn = document.querySelector(\".toggle\").onclick = () => {\n",
    "            demo_obj.classList.toggle(\"dis\"); // 没则添加，有则移除\n",
    "        };\n",
    "        // 是否包含\n",
    "        let contains_btn = document.querySelector(\".contains\").onclick = () => {\n",
    "            let b = demo_obj.classList.contains(\"dis\");\n",
    "            console.log(b);\n",
    "        };\n",
    "    </script>\n",
    "</body>\n",
    "</html>\n",
    "```\n",
    "效果：\n",
    "![3.2.类api.gif](https://img2018.cnblogs.com/blog/1127869/201903/1127869-20190324111335554-623937428.gif)\n",
    "\n",
    "PS：**ES6兼容可以使用`babel`**：`cnpm i babel-core@old` > `babel-core` > **`browser.min.js`**\n",
    "> 回顾：`cnpm`配置：<https://www.cnblogs.com/dotnetcrazy/p/10118756.html#1.1.NPM国内镜像>\n",
    "\n",
    "#### 3.自定义属性\n",
    "\n",
    "**`自定义属性`**：在标签中的`data-自定义属性名`\n",
    "1. 获取自定义属性：`dom.dataset.自定义属性名` or `dom.dataset[\"自定义属性名\"]`\n",
    "2. 设置自定义属性：`dom.dataset.自定义属性名 = xxx` or `dom.dataset[\"自定义属性名\"] = xxx`\n",
    "3. 删除自定义属性：`delete dom.dataset.自定义属性名` or `delete dom.dataset[\"自定义属性名\"]`\n",
    "4. 一般属性：\n",
    "    - 获取某个属性：`dom.getAttribute(\"属性名\")`\n",
    "    - 删除某个属性：`dom.removeAttribute(\"属性名\")`\n",
    "    - 设置某个属性：`dom.setAttribute(\"属性名\", \"值\")`\n",
    "    - 是否包含属性：`dom.hasAttribute(\"属性名\")`\n",
    "\n",
    "举个栗子：\n",
    "```html\n",
    "<div class=\"test\" data-name=\"mmd\" data-test-one=\"test\">自定义属性</div>\n",
    "<script>\n",
    "    // 获取标签的自定义属性值\n",
    "    let list = document.querySelector(\".test\").dataset;\n",
    "    // 获取：dom.dataset.自定义属性名（属性名不包含`data-`)\n",
    "    console.log(list.name);\n",
    "    // PS：test-one名字会改成驼峰命名的变量：testOne\n",
    "    console.log(list.testOne)\n",
    "    // 设置：dom.dataset.自定义属性名 = xxx or dataset[自定义属性名] = xxx\n",
    "    list.name = \"小明\"; // 标签中对应值会变成小明\n",
    "    list.age = 23; // 添加一个属性\n",
    "    // PS：设置为data-test-two\n",
    "    list.testTwo = \"test2\";\n",
    "</script>\n",
    "```\n",
    "输出效果：\n",
    "![3.h5api.png](https://img2018.cnblogs.com/blog/1127869/201903/1127869-20190324083824298-83228614.png)\n",
    "\n",
    "现在可以用`HTML5`把上次的Shopee案例改写了：<a href=\"https://www.cnblogs.com/dotnetcrazy/p/10585254.html\">小计：Shopee批量删除修复~附脚本</a>\n",
    "```js\n",
    "// 核心代码：\n",
    "setInterval(function () {\n",
    "    var btn = document.querySelector(\".delete-button\");\n",
    "    // 只有选择之后才会出现按钮\n",
    "    if (btn) {\n",
    "        // 如果包含disabled类就删除\n",
    "        if (btn.classList.contains(\"disabled\")) {\n",
    "            btn.classList.remove(\"disabled\");\n",
    "        }\n",
    "        // 如果包含disabled属性\n",
    "        if (btn.hasAttribute(\"disabled\")) {\n",
    "            btn.removeAttribute(\"disabled\");\n",
    "        }\n",
    "    }\n",
    "}, 1000);\n",
    "```\n",
    "\n",
    "**PS：妈妈再也不要担心依赖`JQuery`了**\n",
    "\n",
    "#### 扩展：IE下ClassList的兼容解决方案\n",
    "\n",
    "这个摸索好久，网上都是手写js去兼容，然后拿过来用发现。。。。你懂得\n",
    "\n",
    "本来都准备不用classList这么方便的api了，后来发现了神器：**`classList`**\n",
    "\n",
    "贴一下我的前端兼容方案：（`modernizr`上面说了）\n",
    "```js\n",
    "<!--[if lte IE 9]>\n",
    "    <script type=\"text/javascript\" src=\"https://cdn.staticfile.org/modernizr/2.8.3/modernizr.min.js\"></script>\n",
    "    <script type=\"text/javascript\" src=\"https://cdn.staticfile.org/classlist/1.2.20180112/classList.min.js\"></script>\n",
    "<![endif]-->\n",
    "```\n",
    "\n",
    "PS：如果想要兼容`ES6`基础语法、`async/await`，可以使用这两个库：`babel-core`、`babel-polyfill`\n",
    "```\n",
    "// balel-core这个版本是最新的（再新的就不兼容IE了）\n",
    "<script type=\"text/javascript\" src=\"https://cdn.staticfile.org/babel-core/5.8.38/browser.min.js\"></script>\n",
    "```\n",
    "\n",
    "---\n",
    "\n",
    "### 1.4.2.文件相关API\n",
    "\n",
    "1.`FileReader`常用读取文件的方法：\n",
    "- **`reader.readAsText`**：将文件读取为文本\n",
    "- **`reader.readAsDataURL`**：将文件读取为DataURL（Base64）\n",
    "- `reader.readAsBinaryString`：将文件读取为二进制编码\n",
    "- PS：返回结果在`reader.result`中\n",
    "\n",
    "2.`FileReader`中含有的事件：\n",
    "- `onabort`：中断时触发\n",
    "- **`onerror`**：出错时触发\n",
    "- **`onload`**：文件读取成功完成时触发\n",
    "- `onloadend`：读取完成触发，无论成功或失败\n",
    "- `onloadstart`：读取开始时触发\n",
    "- `onprogress`：读取中\n",
    "\n",
    "#### 1.文本上传案例\n",
    "\n",
    "```html\n",
    "<!DOCTYPE html>\n",
    "<html>\n",
    "\n",
    "<head>\n",
    "   <meta charset=\"utf-8\">\n",
    "   <title>文本读取</title>\n",
    "</head>\n",
    "<body>\n",
    "  <input class=\"file\" type=\"file\" name=\"\">\n",
    "  <script>\n",
    "    let file_btn = document.querySelector(\"input\");\n",
    "    // 注意一下this的问题：<http://www.cnblogs.com/dotnetcrazy/p/10061671.html#3.4.特殊的this（重要）>\n",
    "    file_btn.onchange = function () {\n",
    "        // 获取文件\n",
    "        let file = this.files[0];\n",
    "        // type只能识别常用格式，`.md`就不能识别\n",
    "        console.log(file);\n",
    "        // 开始读取（创建读取器）\n",
    "        let reader = new FileReader(); // Python不写new\n",
    "        // 用读取文本的方式来读取\n",
    "        reader.readAsText(file); // 没有返回值\n",
    "        // 取代完成后执行\n",
    "        reader.onload = () => {\n",
    "            console.log(reader.result);\n",
    "        };\n",
    "    };\n",
    "  </script>\n",
    "</body>\n",
    "</html>\n",
    "```\n",
    "\n",
    "图示：\n",
    "![3.3.文本上传.gif](https://img2018.cnblogs.com/blog/1127869/201903/1127869-20190324214732887-900450416.gif)\n",
    "\n",
    "#### 2.图片上传案例\n",
    "\n",
    "```html\n",
    "<!DOCTYPE html>\n",
    "<html>\n",
    "<head>\n",
    "    <meta charset=\"utf-8\">\n",
    "    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n",
    "    <title>图片读取-Base64</title>\n",
    "    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n",
    "</head>\n",
    "<body>\n",
    "  <div><p><input type=\"file\" /></p></div>\n",
    "  <script>\n",
    "    let img_exts = [\".png\", \".gif\", \".jpg\", \".jpeg\", \".bmp\", \".svg\", \".ico\"];\n",
    "    // 获取input对象\n",
    "    let input_obj = document.querySelector(\"input\");\n",
    "    // 文件上传\n",
    "    input_obj.onchange = function () {\n",
    "        // 获取文件信息\n",
    "        let file = input_obj.files[0];\n",
    "        // 获取文件后缀\n",
    "        let ext = file.name.substring(file.name.lastIndexOf('.'));\n",
    "        // 不是图片\n",
    "        if (img_exts.indexOf(ext) == -1) {\n",
    "            alert(\"请上传图片，这个文件格式不支持哦~\");\n",
    "            return\n",
    "        }\n",
    "        // 实例化文件读取器\n",
    "        let reader = new FileReader();\n",
    "        // base64的方式读取文件\n",
    "        reader.readAsDataURL(file); // 没有返回值\n",
    "        // 读取完成后执行\n",
    "        reader.onload = () => {\n",
    "            // 创建一个img对象\n",
    "            let img_obj = document.createElement(\"img\");\n",
    "            // 把读取结果设置为img的src\n",
    "            img_obj.src = reader.result;\n",
    "            // 创建的img对象插入到div中\n",
    "            document.querySelector(\"div\").appendChild(img_obj);\n",
    "        }\n",
    "    }\n",
    "  </script>\n",
    "</body>\n",
    "</html>\n",
    "```\n",
    "图示：\n",
    "![3.4.图片上传.gif](https://img2018.cnblogs.com/blog/1127869/201903/1127869-20190324214025204-1532384961.gif)\n",
    "\n",
    "PS：**核心代码**：\n",
    "```js\n",
    "// 获取input对象\n",
    "let input_obj = document.querySelector(\"input\");\n",
    "// 文件上传\n",
    "input_obj.onchange = function () {\n",
    "   // 获取文件信息\n",
    "   let file = input_obj.files[0];\n",
    "   // 实例化文件读取器\n",
    "   let reader = new FileReader();\n",
    "   // base64的方式读取文件\n",
    "   reader.readAsDataURL(file); // 没有返回值\n",
    "   // 读取完成后执行\n",
    "   reader.onload = () => {\n",
    "     console.log(reader.result);\n",
    "   }\n",
    "}\n",
    "```\n",
    "\n",
    "**PS：一般小文本文件或者图片会用，多个文件或者大文件读取不推荐使用**\n",
    "\n",
    "#### 2.this知识的扩展\n",
    "\n",
    "注意一下this的问题：<http://www.cnblogs.com/dotnetcrazy/p/10061671.html#3.4.特殊的this（重要）>\n",
    "\n",
    "**普通函数的this ==> 谁调用就是谁（经常变：谁调用是谁）**\n",
    "```js\n",
    "function show() {\n",
    "    alert(this); // 1,2,3,4\n",
    "    console.log(this); // [1, 2, 3, 4, show: ƒ]\n",
    "}\n",
    "\n",
    "let arr = [1, 2, 3, 4];\n",
    "arr.show = show;\n",
    "arr.show();\n",
    "```\n",
    "\n",
    "**箭头函数的this ==> 在谁的环境下this就是谁（不变：当前作用域）**\n",
    "```js\n",
    "let arr = [1, 2, 3, 4];\n",
    "arr.show = () => {\n",
    "    alert(this); // [object Window]\n",
    "    console.log(this); // Window\n",
    "}\n",
    "arr.show();\n",
    "```\n",
    "\n",
    "**PS：解决回顾：<https://www.cnblogs.com/dotnetcrazy/p/10061671.html#业余拓展>**\n",
    "\n",
    "### 1.4.3.获取网络状态API\n",
    "\n",
    "1. 是否联网：`window.navigator.onLine`\n",
    "    - PS：**对于APP来说：一般联网就加载最新的资源，没网就加载离线资源**\n",
    "2. 常用事件：主要是看当前是联网还是断网，然后监听对应的断网或者联网事件\n",
    "    - `window.ononline`：联网触发\n",
    "    - `window.onoffline`：离线时候触发\n",
    "\n",
    "**PS：主要是移动端用的比较多**\n",
    "\n",
    "演示案例：\n",
    "```js\n",
    "// 获取网络状态\n",
    "var state = window.navigator.onLine;\n",
    "if (state) {\n",
    "    console.log(\"当前网络可用\");\n",
    "} else {\n",
    "    console.warn(\"断网提醒：当前网络不可用\");\n",
    "}\n",
    "// 断网执行的事件\n",
    "window.onoffline = () => {\n",
    "    document.write(\"网络已断开\");\n",
    "    console.log(window.navigator.onLine)\n",
    "}\n",
    "// 联网执行的事件\n",
    "window.ononline = () => {\n",
    "    document.write(\"网络已连接\");\n",
    "    console.log(window.navigator.onLine)\n",
    "};\n",
    "```\n",
    "**经过实验发现，事件只会执行一次，而且属于有'我没你'的互斥现象**，演示如下：\n",
    "\n",
    "![4.断开网络.gif](https://img2018.cnblogs.com/blog/1127869/201903/1127869-20190325101320906-321270459.gif)\n",
    "![4.重新连接.gif](https://img2018.cnblogs.com/blog/1127869/201903/1127869-20190325101325396-1009753383.gif)\n",
    "\n",
    "PS：**如果已经是联网状态，只会执行断开的事件，重新连接也不会执行联网事件。反之一样~**\n",
    "\n",
    "---\n",
    "\n",
    "### 1.4.4.获取地理位置API（推荐）\n",
    "\n",
    "`geolocation`：定位\n",
    "\n",
    "原理：\n",
    "- PC端：按照IP地址定位（IP库）\n",
    "    - PS：没硬件支持，只能ip走起\n",
    "- 移动：按照WiFi|GPS模块定位（硬件定位）\n",
    "\n",
    "#### 1.简单案例\n",
    "\n",
    "`知识点`：\n",
    "- **`res.coords.longitude`：经度**\n",
    "- **`res.coords.latitude`：纬度**\n",
    "- **`res.coords.speed`：移动速度**\n",
    "    - 实时定位的时候用的多\n",
    "- **`res.coords.accuracy`：精确度**\n",
    "    - 一般低于50，经纬数据就偏差太多\n",
    "\n",
    "案例：\n",
    "```js\n",
    "console.log(window.navigator.userAgent); // PS：Agent也是可以获取的\n",
    "\n",
    "let position = window.navigator.geolocation.getCurrentPosition(res => {\n",
    "    // 获取成功执行\n",
    "    console.log(\"获取成功\", res.coords);\n",
    "    console.log(res.coords.longitude, res.coords.latitude,\"Location in Canada\");\n",
    "}, ex => {\n",
    "    console.log(\"获取失败\", ex);\n",
    "});\n",
    "```\n",
    "动态演示：（PS：`没FQ的可以使用IE演示`）\n",
    "![5.获取成功.gif](https://img2018.cnblogs.com/blog/1127869/201903/1127869-20190327121237110-1465855956.gif)\n",
    "\n",
    "扩展：小程序版地图案例：<https://www.cnblogs.com/dotnetcrazy/p/10597311.html#_map17>\n",
    "\n",
    "#### 2.地图案例\n",
    "\n",
    "PS：很多公司官网介绍里面的地图其实就是通过**`地图生成器`**生成的：<http://api.map.baidu.com/lbsapi/createmap/index.html>\n",
    "> PS：1.2版本不用密钥但是和地图生成器有点渲染的bug，你可以使用对应的API（`<script type=\"text/javascript\" src=\"http://api.map.baidu.com/getscript?v=1.2\"></script>`）\n",
    "\n",
    "分享一下我的密钥：`b3g90mWBIE2VaSCcCuPCXjhj`\n",
    "> `<script type=\"text/javascript\" src=\"http://api.map.baidu.com/getscript?v=2.0&ak=b3g90mWBIE2VaSCcCuPCXjhj\"></script>`\n",
    "\n",
    "![5.baidumap.png](https://img2018.cnblogs.com/blog/1127869/201903/1127869-20190327121436498-1664511336.png)\n",
    "\n",
    "我稍微修改了点，发下demo：\n",
    "```html\n",
    "<!DOCTYPE html>\n",
    "<html>\n",
    "<head>\n",
    "    <meta charset=\"utf-8\">\n",
    "    <title>百度地图API自定义地图</title>\n",
    "    <script type=\"text/javascript\" src=\"http://api.map.baidu.com/getscript?v=2.0&ak=b3g90mWBIE2VaSCcCuPCXjhj\"></script>\n",
    "</head>\n",
    "<body>\n",
    "    <!-- PS：你的宽和高是多少，它就填充多少 -->\n",
    "    <div id=\"baidumap\" style=\"width:1000px;height:500px;\"></div>\n",
    "    <script src=\"../js/baidumap.js\"></script>\n",
    "    <script>\n",
    "        window.onload = () => {\n",
    "            window.navigator.geolocation.getCurrentPosition(res => {\n",
    "                // 初始化百度地图\n",
    "                initMap(\"baidumap\", res.coords.longitude, res.coords.latitude);\n",
    "            }, ex => {\n",
    "                console.warn(\"获取失败\", ex);\n",
    "            });\n",
    "        }\n",
    "    </script>\n",
    "</body>\n",
    "</html>\n",
    "```\n",
    "**PS：你的宽和高是多少，它就填充多少**\n",
    "\n",
    "baidumap.js：\n",
    "```js\n",
    "var map;\n",
    "//创建地图\n",
    "function createMap(id_str, lng, lat) {\n",
    "    map = new BMap.Map(id_str);\n",
    "    map.centerAndZoom(new BMap.Point(lng, lat), 15);\n",
    "}\n",
    "//设置地图事件\n",
    "function setMapEvent() {\n",
    "    map.enableScrollWheelZoom();\n",
    "    map.enableKeyboard();\n",
    "    map.enableDragging();\n",
    "    map.enableDoubleClickZoom()\n",
    "}\n",
    "// 图标单击事件\n",
    "function addClickHandler(target, window) {\n",
    "    target.addEventListener(\"click\", function () {\n",
    "        target.openInfoWindow(window);\n",
    "    });\n",
    "}\n",
    "//向地图添加覆盖物\n",
    "function addMapOverlay(lng, lat, content) {\n",
    "    var markers = [{\n",
    "        content: content, // 一般写详细地址\n",
    "        title: \"\",\n",
    "        imageOffset: {\n",
    "            width: -46,\n",
    "            height: -21\n",
    "        },\n",
    "        position: {\n",
    "            lng: lng,\n",
    "            lat: lat\n",
    "        }\n",
    "    }, ];\n",
    "    for (var index = 0; index < markers.length; index++) {\n",
    "        var point = new BMap.Point(markers[index].position.lng, markers[index].position.lat);\n",
    "        var marker = new BMap.Marker(point, {\n",
    "            icon: new BMap.Icon(\"http://api.map.baidu.com/lbsapi/createmap/images/icon.png\", new BMap.Size(20, 25), {\n",
    "                imageOffset: new BMap.Size(markers[index].imageOffset.width, markers[index].imageOffset.height)\n",
    "            })\n",
    "        });\n",
    "        var label = new BMap.Label(markers[index].title, {\n",
    "            offset: new BMap.Size(25, 5)\n",
    "        });\n",
    "        var opts = {\n",
    "            width: 200,\n",
    "            title: markers[index].title,\n",
    "            enableMessage: false\n",
    "        };\n",
    "        var infoWindow = new BMap.InfoWindow(markers[index].content, opts);\n",
    "        marker.setLabel(label);\n",
    "        addClickHandler(marker, infoWindow);\n",
    "        map.addOverlay(marker);\n",
    "    };\n",
    "    var labels = [];\n",
    "    for (var index = 0; index < labels.length; index++) {\n",
    "        var opt = {\n",
    "            position: new BMap.Point(labels[index].position.lng, labels[index].position.lat)\n",
    "        };\n",
    "        var label = new BMap.Label(labels[index].content, opt);\n",
    "        map.addOverlay(label);\n",
    "    };\n",
    "    var plOpts = [];\n",
    "    var plPath = [];\n",
    "    for (var index = 0; index < plOpts.length; index++) {\n",
    "        var polyline = new BMap.Polyline(plPath[index], plOpts[index]);\n",
    "        map.addOverlay(polyline);\n",
    "    }\n",
    "}\n",
    "//向地图添加控件\n",
    "function addMapControl() {\n",
    "    var scaleControl = new BMap.ScaleControl({\n",
    "        anchor: BMAP_ANCHOR_BOTTOM_LEFT\n",
    "    });\n",
    "    scaleControl.setUnit(BMAP_UNIT_IMPERIAL);\n",
    "    map.addControl(scaleControl);\n",
    "    var navControl = new BMap.NavigationControl({\n",
    "        anchor: BMAP_ANCHOR_TOP_LEFT,\n",
    "        type: 0\n",
    "    });\n",
    "    map.addControl(navControl);\n",
    "    var overviewControl = new BMap.OverviewMapControl({\n",
    "        anchor: BMAP_ANCHOR_BOTTOM_RIGHT,\n",
    "        isOpen: true\n",
    "    });\n",
    "    map.addControl(overviewControl);\n",
    "}\n",
    "//创建和初始化地图函数：id字符串，经度，纬度，详细信息\n",
    "function initMap(id_str, lng, lat, content) {\n",
    "    console.info(id_str, lng, lat, content);\n",
    "    if (content == undefined) {\n",
    "        content = \"I am here\"; //`lng:${lng},lat:${lat}`; // ES6语法（默认参数也是ES6语法）\n",
    "        console.info(\"没有详细描述\");\n",
    "    }\n",
    "    createMap(id_str, lng, lat); //创建地图\n",
    "    setMapEvent(); //设置地图事件\n",
    "    addMapControl(); //向地图添加控件\n",
    "    addMapOverlay(lng, lat, content); //向地图添加覆盖物\n",
    "}\n",
    "```\n",
    "效果：（也进一步验证了，PC端是根据ip来定位的）\n",
    "![5.效果.png](https://img2018.cnblogs.com/blog/1127869/201903/1127869-20190327145834431-115897650.png)\n",
    "\n",
    "---\n",
    "\n",
    "### 1.4.5.本地存储相关API（必看）\n",
    "\n",
    "- `cookie`：浏览器和服务器共享(4k)\n",
    "- **`localStorage`：浏览器独享（5M)**\n",
    "    - **每个域名5M**，没有过期时间（用户不清理的情况下）\n",
    "- `sessionStorage`：当前会话使用的存储\n",
    "    - 用法和localStorage一样，页面关闭就消失了\n",
    "\n",
    "#### 1.基础案例\n",
    "\n",
    "`知识点`：\n",
    "- **设置值：`localStorage.setItem(\"key\", \"value\")`**\n",
    "- **获取值：`localStorage.getItem(\"key\")`**\n",
    "- **删除值：`localStorage.removeItem(\"key\")`**\n",
    "\n",
    "来个案例：\n",
    "```js\n",
    "console.log(\"-------------设置值---------------------\")\n",
    "// 设置值：setItem(key,value)\n",
    "localStorage.setItem(\"id\", 11);\n",
    "localStorage.setItem(\"name\", \"小明\");\n",
    "\n",
    "// 其他实现\n",
    "localStorage.age = 23; // 这种方式也可以\n",
    "localStorage[\"gender\"] = 1; // 这种方式设置也可以\n",
    "\n",
    "console.log(\"-------------获取值---------------------\")\n",
    "\n",
    "//获取值：getItem(key)\n",
    "localStorage.getItem(\"id\");\n",
    "\n",
    "// 其他实现\n",
    "console.log(localStorage.age); // 这种方式也可以\n",
    "console.log(localStorage.mmd); // 如果key不存在=>`undefined`\n",
    "\n",
    "console.log(localStorage[\"gender\"]); // 这种方式也可以\n",
    "console.log(localStorage[\"mmd\"]); // 如果key不存在=>`undefined`\n",
    "\n",
    "console.log(\"-------------删除值---------------------\")\n",
    "\n",
    "// 删除值\n",
    "localStorage.removeItem(\"id\");\n",
    "// 其他实现\n",
    "delete localStorage.age;\n",
    "delete localStorage[\"gender\"];\n",
    "\n",
    "console.log(\"-------------遍历值---------------------\")\n",
    "\n",
    "// 官方推荐的遍历方式\n",
    "for (let i = 0; i < localStorage.length; i++) {\n",
    "    let key = localStorage.key(i);\n",
    "    let value = localStorage.getItem(key);\n",
    "    console.log(key, value);\n",
    "}\n",
    "```\n",
    "输出：\n",
    "```\n",
    "-------------设置值---------------------\n",
    "-------------获取值---------------------\n",
    "23\n",
    "undefined\n",
    "1\n",
    "undefined\n",
    "-------------删除值---------------------\n",
    "-------------遍历值---------------------\n",
    "name 小明\n",
    "```\n",
    "\n",
    "**PS：for in 的方式会把方法也遍历出来，不是我们需要的`key-value`**\n",
    "\n",
    "#### 2.文章草稿案例\n",
    "\n",
    "实际场景：`保存文章草稿`\n",
    "\n",
    "先看一下正常情况：（一般就是添加一个关闭页面的提示）\n",
    "> 但遇到浏览器卡死或者断点就没用了，对于写文章长达好几个小时的作者来说是一个悲剧。。。\n",
    "\n",
    "![4.没保存.gif](https://img2018.cnblogs.com/blog/1127869/201903/1127869-20190327114953640-429835078.gif)\n",
    "\n",
    "通过本地存储实现无缝缓存草稿\n",
    "```html\n",
    "<!DOCTYPE html>\n",
    "<html>\n",
    "<head>\n",
    "    <meta charset=\"utf-8\">\n",
    "    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n",
    "    <title>本地草稿</title>\n",
    "    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n",
    "</head>\n",
    "<body>\n",
    "   <div>\n",
    "    <div>文章内容</div>\n",
    "    <textarea id=\"article\" rows=\"20\" cols=\"50\"></textarea>\n",
    "    <input type=\"button\" value=\"发布文章\" />\n",
    "   </div>\n",
    "    <script>\n",
    "       window.onload = () => {\n",
    "        // 获取文本框对象\n",
    "        let text_obj = document.querySelector(\"#article\");\n",
    "\n",
    "        // 根据文章编号，把草稿内容读取出来（如果没有就为空字符串）\n",
    "        text_obj.value = localStorage[\"5547\"] || '';\n",
    "\n",
    "        // 文本内容改变了就执行（输入事件）\n",
    "        text_obj.oninput = () => {\n",
    "            // 假设当前文章id是5547\n",
    "            localStorage[\"5547\"] = text_obj.value;\n",
    "        }\n",
    "       // 获取按钮对象\n",
    "       let btn_obj = document.querySelector(\"input\");\n",
    "        btn_obj.onclick = () => {\n",
    "           // Ajax请求（我这边省略）\n",
    "           alert(\"文章发布成功！\");\n",
    "           // 清除对应文章的草稿\n",
    "           delete localStorage[\"5547\"];\n",
    "       }\n",
    "      }\n",
    "    </script>\n",
    "</body>\n",
    "</html>\n",
    "```\n",
    "效果演示：\n",
    "![4.保存.gif](https://img2018.cnblogs.com/blog/1127869/201903/1127869-20190327114946249-306032611.gif)\n",
    "\n",
    "**PS：`WebSQL、IndexedDB`因为安全性，现在基本上不用了**（官方也不在维护了）\n",
    "> 题外话：`localStorage`基本上够用了（数据库都暴露在前端了，还有啥安全性？）\n",
    "\n",
    "### 扩展：Canvas画布\n",
    "\n",
    "这个几年前已经说过了，感兴趣的可以自己回顾一下：<http://www.cnblogs.com/dunitian/p/5149156.html>\n",
    "\n",
    "说句实话，搞后端的不大可能自己弄画布相关的API，一般用用类似于`Echarts`就可以了（在Canvas基础上的封装实现）\n",
    "\n",
    "#### 坑点\n",
    "\n",
    "**给`canvas`设置宽高的时候要通过内嵌的属性`width`和`height`来设置，如果通过CSS设置则会失真**\n",
    "> PS：通过CSS设置，相当于把默认画布大小（`302*152`左右）拉伸一下\n",
    "\n",
    "**PS：`SVG`是矢量图，`Canvas`是位图**\n",
    "\n",
    "### H5结语\n",
    "\n",
    "应该，貌似，没有忘记说的吧？几年前贴的思维导图（学习笔记）虽然丑了点，但知识还是挺全的，不清楚的点可以翻哦~\n",
    "> Web大前端时代之：HTML5+CSS3入门系列：<http://www.cnblogs.com/dunitian/p/5121725.html>\n",
    "\n",
    "最后贴一下Demo：\n",
    "1. new：<https://github.com/lotapp/BaseCode/tree/master/javascript/0.H5_C3/H5>\n",
    "2. old：<https://github.com/dunitian/LoTHTML5>\n",
    "\n",
    "**下节预估：`一文入门CSS3`**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2.CSS3\n",
    "\n",
    "官方文档：<http://www.w3school.com.cn/cssref/index.asp>\n",
    "\n",
    "开始之前先说下我准备的案例：<https://github.com/lotapp/h5blog/>\n",
    ">这次是真费了一番功法去准备了一个博客的案例，从`设计`（布局是仿几个模版的）到`PC页面`、再到`响应式`移动端布局（本来是准备直接出移动页面的，后来一想，算了彻底点吧，含`iPad`和`iPhone`）、再到`移动端`H5页面、最后再到`小程序`页面（在H5的基础上简单改了下）算是都弄了个demo\n",
    "\n",
    "先贴下效果图，可能你才有看的动力（前端真的没啥，忘了W3C查一下，我这边整理一下也是为了以后方便）\n",
    "\n",
    "**PC端演示**：<https://github.lesschina.com/html5/>\n",
    "> 这个动态演示的gif太大，大家自己访问吧，这边就贴一个静态图\n",
    "\n",
    "![PC效果图.jpg](https://img2018.cnblogs.com/blog/1127869/201904/1127869-20190416090911703-56471476.jpg)\n",
    "\n",
    "ipad布局：GIF渲染的时候有点小问题，可以直接访问查看效果\n",
    "![ipad.gif](https://img2018.cnblogs.com/blog/1127869/201904/1127869-20190423165139820-126080335.gif)\n",
    "\n",
    "iPhone：GIF渲染的时候有点小问题，可以直接访问查看效果\n",
    "![mobil.gif](https://img2018.cnblogs.com/blog/1127869/201904/1127869-20190423165243084-972987427.gif)\n",
    "\n",
    "**移动端演示**：<http://github.lesschina.com/html5/mobil/>\n",
    "![m.gif](https://img2018.cnblogs.com/blog/1127869/201904/1127869-20190423165656866-455636705.gif)\n",
    "\n",
    "**微信端演示**：<https://github.com/lotapp/H5Blog/tree/master/wechat>\n",
    "![wechat.gif](https://img2018.cnblogs.com/blog/1127869/201904/1127869-20190423165838552-732949800.gif)\n",
    "\n",
    "**注意下图片有时候会有黑边框的问题，设置一下`display:block`就可以了**\n",
    "> PS：本质就是行内块间隙问题（后面会说的）\n",
    "\n",
    "**小程序方面注意点：**\n",
    "- **微信的a标签（`navigator`）是块级元素，而a标签本来是行内元素**\n",
    "- **微信的img标签（`image`）在css中设置`width:100%`是有点小问题的，还需要设置`mode=\"widthFix\"`（或者直接设置这个）**\n",
    "\n",
    "## 2.1.CSS基础\n",
    "\n",
    "基础简单过下，事先说明下：诸如引入、注释、案例就不一一演示了，有个工作1年左右的人都可以熟练掌握，所以基础部分就简单归纳一下**W3C的常用属性列表**了\n",
    "\n",
    "### 2.1.1.文本属性（font、text）\n",
    "\n",
    "官方文档：<http://www.w3school.com.cn/cssref/index.asp#font> or <http://www.w3school.com.cn/cssref/index.asp#text>\n",
    "\n",
    "1. **`color`：文字的颜色**\n",
    "    - eg：`color:red;`、`color: #000;`、`color: rgb(0,0,0);`\n",
    "2. **`font-size`：文字的大小**\n",
    "    - eg：`font-size:12px;`\n",
    "3. **`font-family`：文字的字体**\n",
    "    - eg：使用微软雅黑字体：`font-family:'Microsoft Yahei';`\n",
    "4. **`font-style`：字体是否倾斜**\n",
    "    - eg：字体不倾斜：`font-style:normal;`\n",
    "    - PS：**一般对`i`、`em`这些会导致字体倾斜的标签设置**\n",
    "5. **`font-weight`：文字是否加粗**\n",
    "    - eg：字体加粗：`font-weight:bold;`、字体不加粗：`font-weight:normal;`\n",
    "6. `**line-height**`：文字的行高\n",
    "    - eg：`line-height:24px;`\n",
    "7. `2~6汇总设置`：**`font`：同时设置文字的几个属性**\n",
    "    - 需按顺序写：**`font：是否加粗 字号/行高 字体;`**\n",
    "    - eg：`font:normal 12px/36px 'Microsoft Yahei';`\n",
    "8. **`text-align`：文字水平对齐方式**\n",
    "    - eg：水平居中：`text-align:center`\n",
    "9. **`list-style-type`：设置列表项标记符号**\n",
    "    - 去除符号：`list-style-type:none;`\n",
    "    - PS：**一般都是去除标记用的多**\n",
    "10. **`text-decoration`：文字下划线**\n",
    "    - eg：去除文字下划线：`text-decoration:none;`\n",
    "    - PS：**一般都是去除`a`的下划线**\n",
    "11. `text-indent`：文字首行缩进\n",
    "    - eg：首行缩进2个字符：`text-indent:2em;`\n",
    "12. `text-transform`：控制文本的大小写\n",
    "    - `none`：定义带有小写字母和大写字母的标准的文本(默认)\n",
    "    - `capitalize`：单词中首字母大写\n",
    "    - `uppercase`：单词大写\n",
    "    - `lowercase`：单词小写\n",
    "\n",
    "### 2.1.2.背景相关（background）\n",
    "\n",
    "官方文档：<http://www.w3school.com.cn/cssref/index.asp#background>\n",
    "\n",
    "1. **`background`**：汇总`2~6`\n",
    "    - 参考顺序：**`background: 颜色 url(背景图) no-repeat 定位 fixed`**\n",
    "    - eg：`background:url(雪碧图) no-repeat left -3.025rem;`\n",
    "2. **`background-color`：设置元素的背景颜色**\n",
    "3. **`background-image`：设置元素的背景图像**\n",
    "4. **`background-repeat`：设置是否及如何重复背景图像**\n",
    "5. **`background-position`：设置背景图像的开始位置**\n",
    "    - 垂直居中 + 水平居中：`background-position: center center;`\n",
    "6. `background-attachment`：设置背景图像是否固定或者随着页面的其余部分滚动\n",
    "\n",
    "### 2.1.3.盒模型系（box）\n",
    "\n",
    "**普通盒子`宽 | 高` = `width | height` + `padding` + `border`**\n",
    "\n",
    "#### 1.尺寸属性（width、height）\n",
    "\n",
    "官方文档：<http://www.w3school.com.cn/cssref/index.asp#dimension>\n",
    "\n",
    "1. **`width`：宽度**\n",
    "2. **`height`：高度**\n",
    "3. **`max-width`：最大宽度**\n",
    "4. **`max-height`：最大高度**\n",
    "5. **`min-height`：最小高度**\n",
    "6. **`min-width`：最小宽度**\n",
    "\n",
    "#### 2.边框属性（border）\n",
    "\n",
    "官方文档：<http://www.w3school.com.cn/cssref/index.asp#border>\n",
    "\n",
    "1. **`border`**：2~4汇总\n",
    "    - **参考顺序：`border:width style color;`**\n",
    "    - eg：`border:10px solid red;`\n",
    "2. **`border-width`：设置四条边框的宽度**\n",
    "3. **`border-style`：设置四条边框的样式**\n",
    "    - `solid`：实线、`dashed`：虚线、`dotted`：点线\n",
    "4. **`border-color`：设置四条边框的颜色**\n",
    "\n",
    "PS：**指定边框样式：`border-[top|left|right|bottom]:width style color;`**\n",
    "- eg：`border-top: #00c1de .2rem solid;`\n",
    "\n",
    "#### 3.浮动、溢出、定位（float、overflow、position）\n",
    "\n",
    "官方文档：<http://www.w3school.com.cn/cssref/index.asp#positioning>\n",
    "\n",
    "##### 3.1.浮动\n",
    "\n",
    "浮动本身没什么知识点，清除浮动倒是可以说下：\n",
    "\n",
    "1. **`float: none;`：不浮动(默认值)**\n",
    "2. **`float: left;`：左浮动**\n",
    "3. **`float: right;`：右浮动**\n",
    "4. **`clear: both;`**：清除所有浮动\n",
    "    - PS：可选择：`[left | right | both |none]`\n",
    "\n",
    "以前清除浮动都是在浮动div下添加一个div.clear的空白div，现在基本上都是用`淘宝的伪元素大法`：\n",
    "> PS：有利于SEO\n",
    "\n",
    "```css\n",
    "/* 清除浮动的样式 */\n",
    ".clearfix::before,\n",
    ".clearfix::after {\n",
    "  content: '';\n",
    "  display: table;\n",
    "}\n",
    "\n",
    ".clearfix::after {\n",
    "  clear: both;\n",
    "}\n",
    "\n",
    "/* 兼容IE */\n",
    ".clearfix {\n",
    "  zoom: 1;\n",
    "}\n",
    "```\n",
    "\n",
    "##### 3.2.溢出\n",
    "\n",
    "**overflow：元素溢出**\n",
    "1. visible：超出box也继续显示(默认值)\n",
    "2. hidden：多余内容不可见\n",
    "    - PS：还可以`清除浮动`、`解决margin-top塌陷问题`\n",
    "    - 扩展：<https://www.cnblogs.com/Likebard/p/5899512.html>\n",
    "3. scroll：内容会被修剪，但是浏览器会显示滚动条以便查看其余的内容。\n",
    "4. auto：显示滚动条\n",
    "\n",
    "**PS：如果只只对一个方向可以使用`overflow-x` | `overflow-y`**\n",
    "- eg：移动端主体内容部分：`main{position:absolute;left:0;right:0;top:2.5rem;bottom:2.5rem;overflow-x:hidden;overflow-y:auto;}`\n",
    "\n",
    "##### 3.3.定位\n",
    "\n",
    "1. **`position`：定位**\n",
    "    - **`absolute`：绝对定位**\n",
    "    - **`fixed`：固定定位**\n",
    "    - **`relative`：相对定位**\n",
    "    - **`static`：没有定位(默认值)**\n",
    "2. 偏移（配合`position`使用）\n",
    "    - **`top`**：距离上方的距离\n",
    "    - **`left`**：距离左方的距离\n",
    "    - **`right`**：距离右方的距离\n",
    "    - **`bottom`**：距离下方的距离\n",
    "3. 层级：`z-index`\n",
    "    - 默认为0，可以为负值\n",
    "\n",
    "**PS：绝对定位和固定定位的块元素和行内元素会自动转化为`行内块`元素**\n",
    "\n",
    "![1.叠放顺序.jpg](https://img2018.cnblogs.com/blog/1127869/201904/1127869-20190422112945373-1922260529.jpg)\n",
    "\n",
    "来个经常使用的案例：\n",
    "\n",
    "```html\n",
    "<!DOCTYPE html>\n",
    "<html>\n",
    "<head>\n",
    "    <meta charset=\"UTF-8\">\n",
    "    <title>定位案例</title>\n",
    "    <link rel=\"stylesheet\" href=\"https://at.alicdn.com/t/font_1148101_h5fe3ssorlk.css\">\n",
    "    <style>\n",
    "        header {\n",
    "            width: 100px;\n",
    "            margin: 0 auto;\n",
    "            text-align: center;\n",
    "        }\n",
    "        /* 字体图标 */\n",
    "        header a.icon-guoxue {\n",
    "            /* 去除下划线 */\n",
    "            text-decoration: none;\n",
    "            color: #1a8236;\n",
    "            font-size: 100px;\n",
    "            /* 父类元素设置相对|绝对定位 */\n",
    "            position: relative;\n",
    "        }\n",
    "        header span {\n",
    "            position: absolute;\n",
    "            top: 15px;\n",
    "            right: -5px;\n",
    "            /* 绝对定位和固定定位的块元素和行内元素会自动转化为行内块元素 */\n",
    "            width: 30px;\n",
    "            height: 30px;\n",
    "            font-size: 16px;\n",
    "            /* 居中显示 */\n",
    "            line-height: 30px;\n",
    "            color: white;\n",
    "            background-color: red;\n",
    "            /* 变成圆 */\n",
    "            border-radius: 50%;\n",
    "        }\n",
    "    </style>\n",
    "</head>\n",
    "<body>\n",
    "    <!-- a.iconfont.icon-guoxue>span{99} -->\n",
    "    <header>\n",
    "        <a href=\"#\" class=\"iconfont icon-guoxue\"><span>99</span></a>\n",
    "    </header>\n",
    "</body>\n",
    "</html>\n",
    "```\n",
    "\n",
    "效果：\n",
    "\n",
    "![2.定位案例.png](https://img2018.cnblogs.com/blog/1127869/201904/1127869-20190422115433315-1557629708.png)\n",
    "\n",
    "#### 4.内外边距（margin、padding）\n",
    "\n",
    "官方文档：<http://www.w3school.com.cn/cssref/index.asp#padding>\n",
    "\n",
    "1. **`padding`：汇总属性**\n",
    "    - **参考顺序：`padding：上 右 下 左;`**\n",
    "    - PS：**三个值：`padding: 上 左右 下;`**\n",
    "2. **`padding-bottom`：设置元素的下内边距**\n",
    "3. **`padding-left`：设置元素的左内边距**\n",
    "4. **`padding-right`：设置元素的右内边距**\n",
    "5. **`padding-top`：设置元素的上内边距**\n",
    "\n",
    "官方文档：<http://www.w3school.com.cn/cssref/index.asp#margin>\n",
    "\n",
    "1. **`margin`：汇总属性**\n",
    "    - **eg：水平居中：`margin:x auto;`**\n",
    "    - **参考顺序：`margin：上 右 下 左;`**、**三个值：`margin: 上 左右 下;`**\n",
    "2. **`margin-bottom`：设置元素的下外边距**\n",
    "3. **`margin-left`：设置元素的左外边距**\n",
    "4. **`margin-right`：设置元素的右外边距**\n",
    "5. **`margin-top`：设置元素的上外边距**\n",
    "\n",
    "**PS：有时候有`margin-top`塌陷和`外边距合并`的问题，so ==> 尽量用`padding`**\n",
    "> 重现：在两个盒子嵌套时候，内部的盒子设置的margin-top会加到外边的盒子上，导致内部的盒子margin-top设置失败\n",
    "> 解决：外部盒子设置一个边框，并且在外部盒子里设置`overflow:hidden`，最后使用伪元素`.clearfix:before{content: '';display:table;}`\n",
    "\n",
    "### 2.1.4.扩展与补充\n",
    "\n",
    "#### 1.块元素、内联元素、内联块元素\n",
    "\n",
    "1. **块元素：支持所有样式**\n",
    "    - PS：如果没有设置宽度，默认的宽度为父级宽度100%（不管设不设宽度，都独占一行）\n",
    "2. **内联元素：不支持`width`、`height`、`margin`和`padding`**\n",
    "    - 子元素是内联元素，则父元素可用text-align属性设置子元素水平对齐方式\n",
    "    - 小问题：代码换行，盒子之间会产生间距\n",
    "    - PS：宽高由内容决定，自己设置是不生效的\n",
    "3. **内联块(行内块)：支持所有样式**\n",
    "    - 子元素是内联元素，则父元素可用text-align属性设置子元素水平对齐方式\n",
    "    - 小问题：代码换行，盒子之间会产生间距\n",
    "    - PS：如果没有设置宽高，宽高由内容决定\n",
    "\n",
    "用代码表示一下：\n",
    "\n",
    "1. `display:inline`：内联元素(默认)\n",
    "    - 元素前后没有换行符\n",
    "2. `display:block`：块级元素\n",
    "    - 元素前后会带有换行符\n",
    "3. `display:inline-block`：行内块元素\n",
    "\n",
    "**隐藏：`display:none`此元素不会显示也不占空间，`visibility:hidden;`元素是否可见且占空间**\n",
    "> PS：加过渡动画的时候，visibility有动画效果，而display没有\n",
    "\n",
    "#### 2.内联元素或内联块元素间隙的解决方案\n",
    "\n",
    "以前是只要不去换行就没事了（去掉内联元素之间的换行），现在get到一个新skill：\n",
    "- **将内联元素的父级设置font-size为0，内联元素自身再设置font-size**\n",
    "\n",
    "#### 3.其他属性\n",
    "\n",
    "1. **鼠标显示为手：`cursor:pointer;`**\n",
    "2. **文字不换行：`white-space: nowrap;`**（`normal`是默认值）\n",
    "    - PS：参考<http://www.w3school.com.cn/cssref/pr_text_white-space.asp>\n",
    "3. 设置表格的边框合并：`border-collapse:collapse;`（现在基本上用不到了）\n",
    "\n",
    "---\n",
    "\n",
    "## 2.2.选择器系\n",
    "\n",
    "### 2.2.1.常用选择器\n",
    "\n",
    "**选择器参考手册**：<http://www.w3school.com.cn/cssref/css_selectors.asp>\n",
    "\n",
    "1. 标签选择器\n",
    "    - eg：`p{color:red;}`\n",
    "2. ID选择器\n",
    "    - eg：`#footer{color:#a7a8a9;}`\n",
    "3. 类选择器\n",
    "    - eg：`.copyright {text-align: center;}`\n",
    "4. **层级选择器**：父元素下的子元素（`空格间隔`）\n",
    "    - eg：`.copyright a{color: #a7a8a9;}`：设置copyright类下的a标签颜色\n",
    "5. **组选择器**：同时生效（逗号间隔）\n",
    "    - eg：`em,i {font-style: normal;}`：去除em和i的斜体样式\n",
    "6. **`伪类|伪元素`选择器**：两个:就是伪元素\n",
    "    - eg：伪类：`nav li:hover {color: #000;}`\n",
    "    - eg：伪元素：`.clearfix::after {content:'';display:table;clear:both;}`：清除浮动\n",
    "\n",
    "#### 扩展：伪类与伪元素\n",
    "\n",
    "1. **`:伪类`（一种选择器）eg:`:hover`、`a:active`、`a:visited`**\n",
    "2. **`::伪元素`（通过CSS实现的页面元素）eg：`::before`、`::after`**\n",
    "\n",
    "```css\n",
    "/* 常用伪类 */\n",
    "a:link {color: #FF0000}\t\t/* 未访问的链接 */\n",
    "a:visited {color: #00FF00}\t/* 已访问的链接 */\n",
    "a:hover {color: #FF00FF}\t/* 鼠标移动到链接上 */\n",
    "a:active {color: #0000FF}\t/* 选定的链接 */\n",
    "```\n",
    "\n",
    "### 2.2.2.C3新增系\n",
    "\n",
    "#### 1.属性选择器\n",
    "\n",
    "参考文档：<http://www.w3school.com.cn/css/css_syntax_attribute_selector.asp>\n",
    "\n",
    "以前就有的：**`表单`用的比较多些**\n",
    "\n",
    "- **`[属性名] {}`**：匹配对应的属性即可\n",
    "- **`[属性名=值] {}`**：匹配属性名是某值\n",
    "- 几乎不用：`[属性名|=值]`（属性名以某值开头）和`[属性名~=值]`（属性名包含某值）\n",
    "\n",
    "CSS3新增：**结合`爬虫`有大用**\n",
    "\n",
    "- **`[属性名^=值] {}`**：以值开头\n",
    "    - eg：`a[src^=\"https\"]`：选择src属性以`https`开头的每个`<a>`元素\n",
    "- `[属性名$=值] {}`：以值结束\n",
    "    - eg：`a[src$=\".pdf\"]`：选择src属性以`.pdf`结尾的所有`<a>`元素\n",
    "- `[属性名*=值] {}`：包含某值\n",
    "    - eg：`a[src*=\"baidu.com\"]`：选择src属性包含`baidu.com`子串的每个`<a>`元素\n",
    "\n",
    "来个简单案例：\n",
    "\n",
    "```html5\n",
    "<!DOCTYPE html>\n",
    "<html>\n",
    "<head>\n",
    "    <meta charset=\"UTF-8\">\n",
    "    <title>属性选择器</title>\n",
    "    <style>\n",
    "        input[type=\"password\"] {\n",
    "            background-color: yellow;\n",
    "        }\n",
    "        // name以user开头的表单（eg：用户相关字段）\n",
    "        input[name^=\"user\"] {\n",
    "            background-color: green;\n",
    "        }\n",
    "    </style>\n",
    "</head>\n",
    "<body>\n",
    "    <input type=\"hidden\" name=\"id\"><br/>\n",
    "    <input type=\"text\" name=\"user_name\"><br/>\n",
    "    <input type=\"text\" name=\"user_age\"><br/>\n",
    "    <input type=\"password\" name=\"pass\">\n",
    "</body>\n",
    "</html>\n",
    "```\n",
    "\n",
    "效果：\n",
    "\n",
    "![3.属性选择器.png](https://img2018.cnblogs.com/blog/1127869/201904/1127869-20190423202946071-774296694.png)\n",
    "\n",
    "#### 2.结构性伪类选择器\n",
    "\n",
    "**结构性伪类选择器：`n`可以是`数值`也可以是`表达式`**(eg：`2n+1`)\n",
    "\n",
    "1. **`:nth-child(n) {}`**：选中父元素中正数第n个子元素\n",
    "    - 最特殊：**`:first-child {}`：选中父元素中第一个子元素**\n",
    "2. `:nth-last-child(n) {}`：选中父元素中倒数第n个子元素\n",
    "    - 最特殊：**`:last-child {}`：选中父元素中最后一个子元素**\n",
    "3. **`:nth-of-type(n){}`**：选中父元素中`特定`正数第n个子元素\n",
    "    - PS：和上面的区别等会看个案例\n",
    "4. `:nth-last-child(n) {}`：选中父元素`特定`元素中倒数第n个子元素\n",
    "\n",
    "这个看一个必须来个案例：\n",
    "\n",
    "```html\n",
    "<!DOCTYPE html>\n",
    "<html>\n",
    "<head>\n",
    "    <meta charset=\"UTF-8\">\n",
    "    <title>结构性伪类选择器</title>\n",
    "    <style>\n",
    "        /* 本意先找到bloginfo类下的第一个div，对它第二个span设置样式 */\n",
    "\n",
    "        /* 浏览器会这么找：先去bloginfo类下的第一个div中找第二个元素，然后看看是不是span，如果是则生效 */\n",
    "        /* PS：这边父类下第二个元素不是span，所以不生效 */\n",
    "        .bloginfo div:first-child span:nth-child(2) {\n",
    "            color: red;\n",
    "        }\n",
    "\n",
    "        /* 如果需要达到这个效果可以这么用： */\n",
    "        .bloginfo div:first-child span:nth-child(4) {\n",
    "            color: red;\n",
    "        }\n",
    "\n",
    "        /* 本意先找到bloginfo类下的第二个div，对它第二个span设置样式 */\n",
    "\n",
    "        /* 浏览器会这么找：先去bloginfo类下的第二个div中找所有的span，然后给第二个span设置样式 */\n",
    "        .bloginfo div:last-child span:nth-of-type(2) {\n",
    "            color: green;\n",
    "        }\n",
    "    </style>\n",
    "</head>\n",
    "<body>\n",
    "    <div class=\"bloginfo\">\n",
    "        <div>\n",
    "            <span>逆天</span>\n",
    "            <i>this is test</i>\n",
    "            <time>2019-04-14</time>\n",
    "            <span>【Web】</span>\n",
    "        </div>\n",
    "        <!-- 和上面一样 -->\n",
    "        <div>\n",
    "            <span>逆天</span>\n",
    "            <i>this is test</i>\n",
    "            <time>2019-04-14</time>\n",
    "            <span>【Web】</span>\n",
    "        </div>\n",
    "    </div>\n",
    "</body>\n",
    "</html>\n",
    "```\n",
    "\n",
    "输出图示：\n",
    "\n",
    "![4.结构性伪类选择器.png](https://img2018.cnblogs.com/blog/1127869/201904/1127869-20190423211155768-1777776621.png)\n",
    "\n",
    "#### 3.其他选择器\n",
    "\n",
    "- `:target`：被锚链接指向的时候会触发该选择器\n",
    "- `::selection`：当被鼠标选中的时候的样式\n",
    "- `::first-line`：选中第一行\n",
    "- `::first-letter`：选中第一个字符\n",
    "\n",
    "### 2.2.3.CSS权重（推荐）\n",
    "\n",
    "这个官方文档我倒是没找到，但是流传比较多的是这么个顺序（已验）\n",
    "\n",
    "1. `!important`（**权重值：`10000`**）加在样式属性值后\n",
    "    - eg：`display: block!important;`\n",
    "2. `内联`样式（**权重值：`1000`**）\n",
    "    - eg：`style=\"xx\"`\n",
    "3. `ID`选择器（**权重值：`100`**）\n",
    "    - eg：`#content{xx}`\n",
    "4. `类`，`伪类`和`属性`选择器（**权重值：`10`**）\n",
    "    - eg：`.clearfix`、`:hover`、`input[type=\"text\"]`\n",
    "    - PS：属性选择器参考：<http://www.w3school.com.cn/css/css_syntax_attribute_selector.asp>\n",
    "5. `标签`选择器和`伪元素`选择器（权重值：1）\n",
    "    - eg：`div`、`p`、`:before`\n",
    "6. `通用`选择器（*）、`子`选择器（>）、`相邻`选择器（+）、`同胞`选择器（~）的（**权重值：0**）\n",
    "    - 子选择器参考：<http://www.w3school.com.cn/css/css_selector_child.asp>\n",
    "    - 相邻选择器参考：<http://www.w3school.com.cn/css/css_selector_adjacent_sibling.asp>\n",
    "\n",
    "PS：这个平时用不到，但是对于修改模版样式不生效的时候经常会用到\n",
    "> **你有没有发现有些样式修改了并不生效？这时候CSS权重的重要性就来了**\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.3.新增属性\n",
    "\n",
    "### 2.3.1.背景\n",
    "\n",
    "#### 1.透明背景\n",
    "\n",
    "1. **`opacity`**：设置元素整体透明度\n",
    "2. **`rgba`**：设置带透明色的颜色\n",
    "    - PS：rgba是只设置背景色透明\n",
    "\n",
    "来个区分案例：\n",
    "\n",
    "```html5\n",
    "<!DOCTYPE html>\n",
    "<html>\n",
    "<head>\n",
    "    <meta charset=\"UTF-8\">\n",
    "    <title>透明背景</title>\n",
    "    <style>\n",
    "        div {\n",
    "            width: 200px;\n",
    "            height: 100px;\n",
    "            color: green;\n",
    "            border: 1px solid black;\n",
    "        }\n",
    "\n",
    "        div:nth-child(1) {\n",
    "            background-color: black;\n",
    "            /* 设置整个div的透明色 */\n",
    "            opacity: 0.2;\n",
    "        }\n",
    "\n",
    "        div:nth-child(2) {\n",
    "            /* 只设置背景色的透明度 */\n",
    "            background-color: rgba(0, 0, 0, 0.2);\n",
    "        }\n",
    "    </style>\n",
    "</head>\n",
    "<body>\n",
    "    <div>\n",
    "        <h2>我是一个测试文字</h2>\n",
    "    </div>\n",
    "    <div>\n",
    "        <h2>我是一个测试文字</h2>\n",
    "    </div>\n",
    "</body>\n",
    "</html>\n",
    "```\n",
    "\n",
    "效果：\n",
    "\n",
    "![5.透明背景.png](https://img2018.cnblogs.com/blog/1127869/201904/1127869-20190423221933230-322467832.png)\n",
    "\n",
    "#### 2.背景尺寸\n",
    "\n",
    "官方案例：<http://www.w3school.com.cn/tiy/c.asp?f=css_background-size>\n",
    "\n",
    "**`background-size`：规定背景图片的尺寸**\n",
    "- **`background-size:30% 40%;`**：可以是数值或百分比\n",
    "    - PS：先宽后高\n",
    "- **`contain`**：等比缩放，直至宽或者高和盒子相同\n",
    "    - PS：盒子有空闲空间\n",
    "- `cover`：等比缩放，并填充慢容器\n",
    "    - PS：图像可能显示不完整\n",
    "\n",
    "看个案例：\n",
    "\n",
    "```html\n",
    "<!DOCTYPE html>\n",
    "<html>\n",
    "<head>\n",
    "    <meta charset=\"UTF-8\">\n",
    "    <title>背景尺寸</title>\n",
    "    <style>\n",
    "        div {\n",
    "            width: 100px;\n",
    "            height: 100px;\n",
    "            background: url(http://github.lesschina.com/html5/images/logo.gif) no-repeat;\n",
    "            border: 1px solid black;\n",
    "        }\n",
    "\n",
    "        div:nth-child(1) {\n",
    "            /* 宽 高 */\n",
    "            background-size: 100% 50%;\n",
    "        }\n",
    "\n",
    "        div:nth-child(2) {\n",
    "            /* 等比缩放，直至宽或者高和盒子相同 */\n",
    "            background-size: contain;\n",
    "        }\n",
    "\n",
    "        div:nth-child(3) {\n",
    "            /* 等比缩放，并填充慢容器 */\n",
    "            background-size: cover;\n",
    "        }\n",
    "    </style>\n",
    "</head>\n",
    "<body>\n",
    "    <div></div>\n",
    "    <div></div>\n",
    "    <div></div>\n",
    "</body>\n",
    "</html>\n",
    "```\n",
    "\n",
    "效果图：\n",
    "\n",
    "![5.背景图尺寸.png](https://img2018.cnblogs.com/blog/1127869/201904/1127869-20190423215457198-1191472512.png)\n",
    "\n",
    "\n",
    "#### 3.双背景\n",
    "\n",
    "**CSS3可以设置两个背景图：`background-image:url(xxx),url(xxx);`**（叠加显示）\n",
    "\n",
    "看个案例：\n",
    "\n",
    "```html\n",
    "<!DOCTYPE html>\n",
    "<html>\n",
    "<head>\n",
    "    <meta charset=\"UTF-8\">\n",
    "    <title>两个背景图</title>\n",
    "    <style>\n",
    "        div {\n",
    "            width: 260px;\n",
    "            height: 462px;\n",
    "            /* 三句合为一句写 */\n",
    "            background: url(https://github.lesschina.com/html5/images/logo.gif) no-repeat center center, url(https://github.lesschina.com/html5/images/banner/b02.jpg) no-repeat center;\n",
    "            /* background-image: url(https://github.lesschina.com/html5/images/logo.gif), url(https://github.lesschina.com/html5/images/banner/b02.jpg); */\n",
    "            /* background-repeat: no-repeat; */\n",
    "            /* 垂直居中 + 水平居中 */\n",
    "            /* background-position: center center; */\n",
    "            border: 1px solid black;\n",
    "        }\n",
    "    </style>\n",
    "</head>\n",
    "<body>\n",
    "    <div></div>\n",
    "</body>\n",
    "</html>\n",
    "```\n",
    "\n",
    "效果：\n",
    "\n",
    "![6.双背景.png](https://img2018.cnblogs.com/blog/1127869/201904/1127869-20190423223229627-732880597.png)\n",
    "\n",
    "#### 3.不常用\n",
    "\n",
    "1. `background-origin`：设置背景图片的定位区域：\n",
    "    - `padding-box`：以内边距(`padding`)左上角为起点进行定位（默认值）\n",
    "    - `border-box`：以边框(`border`)左上角为起点进行定位\n",
    "    - `content-box`：以内容区域(`content`)左上角为起点\n",
    "2. `background-clip`：规定背景的绘制区域\n",
    "    - `border-box`：背景图片在整个容器中显示\n",
    "    - `padding-box`：背景图片在内边距+正文区域显示\n",
    "    - `content-box`：背景图片只在正文区域显示\n",
    "\n",
    "### 2.3.2.边框\n",
    "\n",
    "#### 知识点\n",
    "\n",
    "1. **`border-radius`：边框圆角**\n",
    "2. **`border-image`：边框图片**（eg：`border-image:url(border.png) 20 round;`）\n",
    "    - **设置边框图片：`border-image-source: url(\"xx\");`**\n",
    "    - **边框图片裁切：`border-image-slice: 数值;`**\n",
    "        - PS：`不需要带单位`\n",
    "    - `border-image-repeat`: 设置边框图片的平铺方式（如何重复图像边框）\n",
    "        - `stretch`：拉伸（默认）\n",
    "        - **`round`：环绕的方式重复显示**\n",
    "        - `repeat`：重复显示\n",
    "            - 一般都使用round，repeat的方式很多时候都有点小问题\n",
    "    - **图像边框宽度：`border-image-width: 数值;`**\n",
    "3. **`box-shadow: 水平阴影的位置 垂直阴影的位置 [模糊距离] [阴影的尺寸] [阴影的颜色] [内|外阴影];`**\n",
    "    - PS：`text-shadow`：设置文本阴影\n",
    "    - eg：`box-shadow: 0px 0px 10px #fff;`（水平阴影位置，垂直阴影位置，模糊距离，颜色）\n",
    "    - 文档：<http://www.w3school.com.cn/cssref/pr_box-shadow.asp>\n",
    "4. 颜色渐变：**这个和PS里面的颜色渐变一样**\n",
    "    - **线性渐变：`linear-gradient`**\n",
    "        - 可以通过方向和角度：`to [ right | top | bottom | left ]` or `0deg：从下向上渐变]，90deg：从左向右`\n",
    "        - eg：从右下到左上、从蓝色渐变到红色`linear-gradient(to left top, blue, red);`\n",
    "        - 参考文档：<https://developer.mozilla.org/zh-CN/docs/Web/CSS/linear-gradient>\n",
    "    - 径向渐变：`radial-gradient`\n",
    "        - 参考文档：<https://developer.mozilla.org/zh-CN/docs/Web/CSS/radial-gradient>\n",
    "    - **PS：渐变其实是一种图片，一般都是设置`background-image`**\n",
    "\n",
    "#### 1.圆角与渐变\n",
    "\n",
    "这个比较简单，简单说下常用的两种即可：\n",
    "\n",
    "```html\n",
    "<!DOCTYPE html>\n",
    "<html>\n",
    "<head>\n",
    "    <meta charset=\"UTF-8\">\n",
    "    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n",
    "    <title>圆角案例</title>\n",
    "    <style>\n",
    "        /* 椭圆矩形 */\n",
    "        div:first-child {\n",
    "            width: 200px;\n",
    "            height: 200px;\n",
    "            background: black;\n",
    "            border-radius: 10px;\n",
    "        }\n",
    "        /* 设置图片大小，并显示为圆 */\n",
    "        div img {\n",
    "            /* 半径是长度的50%==>圆 */\n",
    "            border-radius: 50%;\n",
    "            width: 200px;\n",
    "            height: 200px;\n",
    "        }\n",
    "        div:last-child i {\n",
    "            display: block;\n",
    "            width: 200px;\n",
    "            height: 200px;\n",
    "            padding: 5px;\n",
    "            border-radius: 50%;\n",
    "            /* 设置一个渐变色 */\n",
    "            background: linear-gradient(to top right, rgba(0, 153, 255, .9), rgba(42, 228, 197, .7));\n",
    "        }\n",
    "    </style>\n",
    "</head>\n",
    "<body>\n",
    "    <div></div><br />\n",
    "    <div><img src=\"https://github.lesschina.com/html5/images/avatar.jpg\"></div><br />\n",
    "    <div><i><img src=\"https://github.lesschina.com/html5/images/avatar.jpg\"></i></div>\n",
    "</body>\n",
    "\n",
    "</html>\n",
    "```\n",
    "\n",
    "图示：\n",
    "\n",
    "![8.圆边.png](https://img2018.cnblogs.com/blog/1127869/201904/1127869-20190424154245371-690073375.png)\n",
    "\n",
    "#### 2.中国风边框图片案例\n",
    "\n",
    "我先用PS来简单扩充一下裁切的概念：（**类比Padding和margin的设置方法，然后不算单位**）\n",
    "\n",
    "![7.边框裁剪示意图.jpg](https://img2018.cnblogs.com/blog/1127869/201904/1127869-20190424152152070-1438830928.jpg)\n",
    "\n",
    "看个简单案例：（平时设置网站风格的时候用的比较多，以前是设置背景图片，现在省事也省带宽了）\n",
    "\n",
    "```html\n",
    "<!DOCTYPE html>\n",
    "<html>\n",
    "<head>\n",
    "    <meta charset=\"UTF-8\">\n",
    "    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n",
    "    <title>边框图片</title>\n",
    "    <style>\n",
    "        div {\n",
    "            width: 300px;\n",
    "            height: 300px;\n",
    "            border: 50px solid black;\n",
    "            font-family: '钟齐流江毛笔草体';\n",
    "            font-size: 30px;\n",
    "            line-height: 300px;\n",
    "            /* 竖排显示(从左往右方向) */\n",
    "            writing-mode: vertical-lr;\n",
    "            text-align: center;\n",
    "            float: left;\n",
    "        }\n",
    "        div:nth-child(2) {\n",
    "            /* 设置边框图片 */\n",
    "            border-image-source: url(../images/1.png);\n",
    "        }\n",
    "        div:nth-child(3) {\n",
    "            border-image: url(../images/1.png) 54 80 62 68;\n",
    "            /* border-image-source: url(../images/1.png); */\n",
    "            /* 设置边框图片的裁切 */\n",
    "            /* border-image-slice: 54 80 62 68; */\n",
    "        }\n",
    "    </style>\n",
    "</head>\n",
    "<body>\n",
    "    <div>微信公众号 逸鹏说道</div>\n",
    "    <div>微信公众号 逸鹏说道</div>\n",
    "    <div>微信公众号 逸鹏说道</div>\n",
    "</body>\n",
    "</html>\n",
    "```\n",
    "\n",
    "图示：\n",
    "\n",
    "![7.边框图片demo.jpg](https://img2018.cnblogs.com/blog/1127869/201904/1127869-20190424151943374-736850332.jpg)\n",
    "\n",
    "#### 3.边框图片平铺方式\n",
    "\n",
    "平铺方式简单说下：\n",
    "\n",
    "```html\n",
    "<!DOCTYPE html>\n",
    "<html>\n",
    "<head>\n",
    "    <meta charset=\"UTF-8\">\n",
    "    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n",
    "    <title>边框图片2</title>\n",
    "    <style>\n",
    "        div {\n",
    "            width: 250px;\n",
    "            height: 250px;\n",
    "            margin-right: 20px;\n",
    "            border: 50px solid black;\n",
    "            font-size: 25px;\n",
    "            line-height: 300px;\n",
    "            /* 竖排显示(从左往右方向) */\n",
    "            writing-mode: vertical-lr;\n",
    "            text-align: center;\n",
    "            float: left;\n",
    "        }\n",
    "        div:first-child {\n",
    "            border-image: url(../images/2.png);\n",
    "        }\n",
    "        div:nth-child(2) {\n",
    "            /* 裁切20就可以把四个角的爱心完美扣下了 */\n",
    "            border-image: url(../images/2.png) 20;\n",
    "        }\n",
    "        div:nth-child(3) {\n",
    "            /* 设置边框图片的平铺方式 */\n",
    "            border-image: url(../images/2.png) 20 repeat;\n",
    "        }\n",
    "        div:last-child {\n",
    "            /* 推荐方式 */\n",
    "            border-image: url(../images/2.png) 20 round;\n",
    "        }\n",
    "    </style>\n",
    "</head>\n",
    "<body>\n",
    "    <div>只设置了边框图片</div>\n",
    "    <div>设置边框图片和裁切</div>\n",
    "    <div>边框平铺方式为重复</div>\n",
    "    <div>边框平铺方式为环绕</div>\n",
    "</body>\n",
    "</html>\n",
    "```\n",
    "\n",
    "图示：\n",
    "\n",
    "![7.边框图片重复.png](https://img2018.cnblogs.com/blog/1127869/201904/1127869-20190424151552546-2019879021.png)\n",
    "\n",
    "课后拓展：\n",
    "\n",
    "<a href=\"https://segmentfault.com/a/1190000010969367\" target=\"_blank\">CSS3 border-image 彻底明白</a>\n",
    "\n",
    "---\n",
    "\n",
    "### 2.3.3.过渡（重点）\n",
    "\n",
    "#### 1.知识点\n",
    "\n",
    "**我的理解：如果一个元素设置了`transition`，那么它属性改变的时候就会呈现出动画状态**\n",
    "\n",
    "**`transition: property duration timing-function delay`**\n",
    "1. `transition-property`：设置过渡的属性\n",
    "    - eg：width height background-color\n",
    "2. `transition-duration`：设置过渡的时间\n",
    "    - eg：1s 500ms\n",
    "3. `transition-timing-function`：设置过渡的运动方式\n",
    "    - 常用：`linear`(匀速). `ease`(缓冲运动)\n",
    "4. `transition-delay`：设置动画的延迟\n",
    "    - PS：一般用不到\n",
    "\n",
    "**PS：一般都这么用：`transition: all 500ms ease;`**\n",
    "\n",
    "#### 2.简单案例\n",
    "\n",
    "看个例子：\n",
    "\n",
    "```html\n",
    "<!DOCTYPE html>\n",
    "<html>\n",
    "<head>\n",
    "    <meta charset=\"UTF-8\">\n",
    "    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n",
    "    <title>过渡动画</title>\n",
    "    <style>\n",
    "        div {\n",
    "            width: 300px;\n",
    "            height: 300px;\n",
    "            margin: 0 auto;\n",
    "            background-color: black;\n",
    "            /* 设置了transition，那div任何属性的改动都会有过渡动画 */\n",
    "            transition: all 1s ease;\n",
    "        }\n",
    "\n",
    "        div:hover {\n",
    "            background-color: yellow;\n",
    "        }\n",
    "    </style>\n",
    "</head>\n",
    "<body>\n",
    "    <div></div>\n",
    "</body>\n",
    "</html>\n",
    "```\n",
    "\n",
    "图示：\n",
    "\n",
    "![9.过渡动画.gif](https://img2018.cnblogs.com/blog/1127869/201904/1127869-20190424161615278-2046256157.gif)\n",
    "\n",
    "#### 4.特殊案例\n",
    "\n",
    "只有一个属性是没有过渡动画的：**`display:none` ==》 `display:block`**\n",
    "\n",
    "看个区分案例：\n",
    "\n",
    "```hmtl\n",
    "<!DOCTYPE html>\n",
    "<html>\n",
    "<head>\n",
    "    <meta charset=\"UTF-8\">\n",
    "    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n",
    "    <title>特殊案例</title>\n",
    "    <style>\n",
    "        div {\n",
    "            width: 300px;\n",
    "            height: 300px;\n",
    "            margin: 0 auto;\n",
    "            background-color: black;\n",
    "            /* 设置了transition，那div任何属性的改动都会有过渡动画 */\n",
    "            transition: all 500ms ease;\n",
    "        }\n",
    "        /* 第一个盒子使用visibility的方式显示和隐藏 */\n",
    "        div:first-child {\n",
    "            visibility: hidden;\n",
    "        }\n",
    "        body:hover div:first-child {\n",
    "            visibility: visible;\n",
    "            background-color: yellow;\n",
    "        }\n",
    "        /* 第二个盒子使用display的方式显示和隐藏 */\n",
    "        div:last-child {\n",
    "            display: none;\n",
    "        }\n",
    "        body:hover div:last-child {\n",
    "            display: block;\n",
    "            background-color: yellow;\n",
    "        }\n",
    "    </style>\n",
    "</head>\n",
    "<body>\n",
    "    <div>visibility</div>\n",
    "    <div>display</div>\n",
    "</body>\n",
    "</html>\n",
    "```\n",
    "\n",
    "图示：(**`visibility`和`display`的区别不用说了吧？无非是一个占空间一个不占**）\n",
    "\n",
    "![9.隐藏和显示.gif](https://img2018.cnblogs.com/blog/1127869/201904/1127869-20190424163048884-2002767866.gif)\n",
    "\n",
    "### 2.3.4.transform转换\n",
    "\n",
    "**经验：如果多个变换一起用的，那么顺序为：**`从后往前执行`**\n",
    "> `transform`一定要加初始值**（不然在边角的时候有小问题）\n",
    "\n",
    "#### 1.2D转换\n",
    "\n",
    "1. **位移**\n",
    "    - **`transform: translate(x轴,y轴);`**\n",
    "        - eg：`transform: translate(100px,100px);`\n",
    "    - PS：相对自身位置发生的位置改变\n",
    "2. **缩放**\n",
    "    - **`transform: scale(x,y);`**\n",
    "        - eg：`transform: scale(0.5,1);`\n",
    "    - PS：倍数关系\n",
    "3. 旋转\n",
    "    - `transform: rotate(60deg);`\n",
    "    - PS：`deg`是角度\n",
    "4. 倾斜\n",
    "    - `transform: skew(x轴,y轴);`\n",
    "    - eg：`transform: skew(30deg,30deg);`\n",
    "\n",
    "看个案例：\n",
    "\n",
    "```html\n",
    "<!DOCTYPE html>\n",
    "<html>\n",
    "<head>\n",
    "    <meta charset=\"UTF-8\">\n",
    "    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n",
    "    <title>2d变换</title>\n",
    "    <style>\n",
    "        div {\n",
    "            width: 200px;\n",
    "            height: 200px;\n",
    "            float: left;\n",
    "            border: 1px solid black;\n",
    "            background-color: yellow;\n",
    "            /* 添加一个过渡动画 */\n",
    "            transition: all 1s ease;\n",
    "        }\n",
    "        /* x轴平移50px，y轴平移100px */\n",
    "        div:first-child:hover {\n",
    "            background-color: green;\n",
    "            /* 逗号别忘记了 */\n",
    "            transform: translate(50px, 100px);\n",
    "        }\n",
    "        /* x轴放大1.1倍，y轴放大2倍 */\n",
    "        div:nth-child(2):hover {\n",
    "            transform: scale(1.1, 2)\n",
    "        }\n",
    "        /* 旋转90度 */\n",
    "        div:last-child:hover {\n",
    "            transform: rotate(90deg)\n",
    "        }\n",
    "\n",
    "    </style>\n",
    "</head>\n",
    "<body>\n",
    "    <div></div>\n",
    "    <div></div>\n",
    "    <div></div>\n",
    "</body>\n",
    "</html>\n",
    "```\n",
    "\n",
    "图示：（PS：**CSS3样式都不会改变盒模型**，这个案例就可以看出了）\n",
    "\n",
    "![10.2d变换.gif](https://img2018.cnblogs.com/blog/1127869/201904/1127869-20190424183034251-1984129591.gif)\n",
    "\n",
    "#### 2.3D转换\n",
    "\n",
    "1. 位移\n",
    "    - transform: translateX()  translateY()   translateZ()\n",
    "2. 缩放\n",
    "    - transform: scaleX(0.5)  scaleY(1)  scaleZ(1);\n",
    "3. 旋转\n",
    "    - transform: rotateX(60deg)  rotateY(60deg)  rotateZ(60deg);\n",
    "4. 倾斜\n",
    "    - transform: skewX(30deg) skewY(30deg);\n",
    "\n",
    "这两个是视觉更好体验的参数：（`推荐`）\n",
    "\n",
    "1. **`transform-style:preserve-3d`**：允许子元素呈现3d视图\n",
    "2. **`perspective`：设置透视距离**\n",
    "    - eg：`transform: perspective(800px);`\n",
    "    - PS：一般都是600px~1000px\n",
    "\n",
    "其他参数：\n",
    "\n",
    "- `tranform-origin`：设置变形的中心点\n",
    "- `backface-visibility`：设置盒子背面是否可见\n",
    "\n",
    "演示案例：\n",
    "\n",
    "```html\n",
    "<!DOCTYPE html>\n",
    "<html>\n",
    "<head>\n",
    "    <meta charset=\"UTF-8\">\n",
    "    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n",
    "    <title>3d变换</title>\n",
    "    <style>\n",
    "        .grandfather {\n",
    "            width: 300px;\n",
    "            height: 300px;\n",
    "            margin: 300px auto;\n",
    "            background-color: rgba(255, 0, 0, 0.3);\n",
    "            /* 允许子元素呈现3d视图 */\n",
    "            transform-style: preserve-3d;\n",
    "        }\n",
    "        .parent {\n",
    "            width: 100%;\n",
    "            height: 100%;\n",
    "            background-color: rgba(0, 255, 0, 0.3);\n",
    "            /* 设置初始值 */\n",
    "            transform: perspective(0) translateZ(0);\n",
    "            /* 允许子元素呈现3d视图 */\n",
    "            transform-style: preserve-3d;\n",
    "            /* 设置一个补间动画 */\n",
    "            transition: all 1s ease;\n",
    "        }\n",
    "        .child {\n",
    "            width: 100%;\n",
    "            height: 50%;\n",
    "            background-color: rgba(0, 255, 255, 0.3);\n",
    "            /* 设置初始值 */\n",
    "            transform: perspective(0) translateZ(0);\n",
    "            /* 设置一个补间动画 */\n",
    "            transition: all 1s ease;\n",
    "        }\n",
    "        .parent:hover {\n",
    "            /* z轴移动200px（铺面而来） */\n",
    "            transform: perspective(800px) translateZ(200px);\n",
    "        }\n",
    "        .child:hover {\n",
    "            /* z轴移动200px（铺面而来） */\n",
    "            transform: perspective(800px) translateZ(100px);\n",
    "        }\n",
    "    </style>\n",
    "</head>\n",
    "<body>\n",
    "    <div class=\"grandfather\">\n",
    "        <div class=\"parent\">\n",
    "            <div class=\"child\"></div>\n",
    "        </div>\n",
    "    </div>\n",
    "</body>\n",
    "</html>\n",
    "```\n",
    "\n",
    "图示：\n",
    "\n",
    "![10.3d变换](https://img2018.cnblogs.com/blog/1127869/201904/1127869-20190424193322625-1168312920.gif)\n",
    "\n",
    "PS：更多复杂功能，如果感兴趣可以看看**`WebGL`**\n",
    "\n",
    "---\n",
    "\n",
    "### 2.3.5.动画\n",
    "\n",
    "animation基本上不太用，复杂的动画我一般使用：`Animate.css`，简单的动画`transition`+`transform`就够了，如果是滚动动画之类的我一般用`scrollreveal.js`\n",
    "\n",
    "**`animation:动画名称 动画时间 动画曲线 延迟时间 播放次数 是否反向运动 动画停留在哪一帧;`**\n",
    "- eg：`animation: move_search 1s linear 0.5s forwards;`(动画名称 动画时间 动画曲线 延迟时间 停留在最后一帧)\n",
    "\n",
    "1. `@keyframes`：定义关键帧动画\n",
    "2. `animation-name`：动画名称\n",
    "3. `animation-duration`：动画时间\n",
    "4. `animation-timing-function`：动画曲线\n",
    "    - `linear`(匀速)、`ease`(缓冲)、`steps`(做帧动画的`步数`)\n",
    "5. `animation-delay`：动画延迟\n",
    "6. `animation-iteration-count`：动画播放次数\n",
    "    - n(指定次数)、infinite(循环)\n",
    "7. `animation-direction`：动画结束后是否反向还原\n",
    "    - normal、alternate(反向)\n",
    "8. `animation-play-state`：动画状态\n",
    "    - paused(停止)、running(运动)\n",
    "9.  `animation-fill-mode`：动画前后的状态\n",
    "    - none(缺省)、**forwards**(结束时停留在最后一帧)\n",
    "    - backwards(开始时停留在定义的开始帧)、both(前后都应用)\n",
    "\n",
    "**PS：如果设置动画集使用的是百分比，那么这个百分比是指相对整个动画的执行时间**\n",
    "\n",
    "简单看个案例就收工吧：\n",
    "\n",
    "这次先看效果：\n",
    "\n",
    "![11.动画.gif](https://img2018.cnblogs.com/blog/1127869/201904/1127869-20190424205439231-1190448224.gif)\n",
    "\n",
    "```html\n",
    "<!DOCTYPE html>\n",
    "<html>\n",
    "\n",
    "<head>\n",
    "    <meta charset=\"UTF-8\">\n",
    "    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n",
    "    <title>animate动画</title>\n",
    "    <style>\n",
    "        body {\n",
    "            width: 100%;\n",
    "            height: 100%;\n",
    "            background-color: rgb(22, 186, 157);\n",
    "        }\n",
    "\n",
    "        header {\n",
    "            width: 50%;\n",
    "            margin: 100px auto;\n",
    "        }\n",
    "\n",
    "        .search {\n",
    "            height: 50px;\n",
    "            border: 1px solid white;\n",
    "            /* 水平阴影位置，垂直阴影位置，模糊距离，颜色 */\n",
    "            box-shadow: 0px 0px 10px #fff;\n",
    "\n",
    "            /* 为动画准备的相对定位 */\n",
    "            position: relative;\n",
    "            /* animation:动画名称 动画时间 动画曲线 停留在最后一帧 */\n",
    "            animation: move_search 1s linear forwards;\n",
    "        }\n",
    "\n",
    "        /* 最简单的移动，也可以百分百来设置进度 */\n",
    "        @keyframes move_search {\n",
    "            from {\n",
    "                left: -200%;\n",
    "            }\n",
    "\n",
    "            to {\n",
    "                left: 0;\n",
    "            }\n",
    "        }\n",
    "\n",
    "        .search div {\n",
    "            color: white;\n",
    "            padding-left: 10px;\n",
    "            /* 为了居中 */\n",
    "            line-height: 50px;\n",
    "\n",
    "            /* 为了动画而设置 */\n",
    "            width: 0;\n",
    "            height: 50px;\n",
    "            overflow: hidden;\n",
    "\n",
    "            /* animation:动画名称 动画时间 8帧显示完 停留在最后一帧 延迟1s显示 */\n",
    "            animation: show_font 1.5s steps(8) forwards 1s;\n",
    "        }\n",
    "\n",
    "        @keyframes show_font {\n",
    "            0% {\n",
    "                width: 0;\n",
    "            }\n",
    "\n",
    "            50% {\n",
    "                width: 75px;\n",
    "            }\n",
    "\n",
    "            100% {\n",
    "                width: 130px;\n",
    "            }\n",
    "        }\n",
    "    </style>\n",
    "</head>\n",
    "\n",
    "<body>\n",
    "    <header>\n",
    "        <div class=\"search\">\n",
    "            <div>公众号：逸鹏说道</div>\n",
    "        </div>\n",
    "    </header>\n",
    "</body>\n",
    "\n",
    "</html>\n",
    "```\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.4.布局相关\n",
    "\n",
    "### 2.4.1.弹性布局\n",
    "\n",
    "这个基本上用的前端框架都包含了（eg：`bootstrap`），这边简单看下即可\n",
    "\n",
    "```html\n",
    "<!DOCTYPE html>\n",
    "<html>\n",
    "\n",
    "<head>\n",
    "    <meta charset=\"UTF-8\">\n",
    "    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n",
    "    <title>弹性</title>\n",
    "    <style media=\"screen\">\n",
    "        ul {\n",
    "            display: flex;\n",
    "        }\n",
    "        ul li {\n",
    "            list-style: none;\n",
    "            border: 1px solid black;\n",
    "            background-color: yellow;\n",
    "        }\n",
    "        ul li:first-child {\n",
    "            /* 权重为1 */\n",
    "            flex: 1;\n",
    "        }\n",
    "        ul li:nth-child(2) {\n",
    "            /* 权重为2 */\n",
    "            flex: 2;\n",
    "            /* 一般都配合min-宽高来使用 */\n",
    "            min-width: 100px;\n",
    "        }\n",
    "        ul li:last-child {\n",
    "            /* 权重为2 */\n",
    "            flex: 2;\n",
    "        }\n",
    "    </style>\n",
    "</head>\n",
    "<body>\n",
    "    <ul>\n",
    "        <li>1</li>\n",
    "        <li>2</li>\n",
    "        <li>3</li>\n",
    "    </ul>\n",
    "</body>\n",
    "</html>\n",
    "```\n",
    "\n",
    "### 2.4.2.响应式布局（推荐）\n",
    "\n",
    "**个人理解：规定一个最大或者最小的边界值，超过这个值就对指定元素设置指定样式**\n",
    "\n",
    "不难，看下demo里面的code片段就结束吧：\n",
    "\n",
    "```css\n",
    "/* 屏幕小于等于1200px使用如下CSS（非宽屏） */\n",
    "@media screen and (max-width: 1200px) {\n",
    "  main {\n",
    "    width: 95%;\n",
    "  }\n",
    "\n",
    "  /* 文章宽屏显示 */\n",
    "  main article,\n",
    "  .copyright {\n",
    "    width: 100%;\n",
    "  }\n",
    "\n",
    "  /* 侧边栏隐藏 */\n",
    "  main aside {\n",
    "    display: none;\n",
    "  }\n",
    "\n",
    "  /* 页脚宽屏显示 */\n",
    "  .copyright {\n",
    "    width: 100%;\n",
    "    min-width: auto;\n",
    "  }\n",
    "}\n",
    "```\n",
    "\n",
    "**注意一下：响应式看起来加载的东西少了（eg：移动端）但其实和PC端请求页面大小一样（该加载的还是要加载，只是隐藏而已）**\n",
    "\n",
    "最后再提一下移动端的`meta`，一般都这么设置：**`宽度为屏幕宽度，且不允许用户缩放`**\n",
    "> `<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">`\n",
    "\n",
    "## 插件扩展\n",
    "\n",
    "### 通过`Autoprefixer`自动给添加不同浏览器CSS3前缀\n",
    "\n",
    "有些CSS3在谷歌浏览器、火狐、IE的老版本中可能不是标准名称，这时候可以通过`Autoprefixer`快速来兼容旧浏览器，之前写过文章，可以看看：\n",
    "> <a href=\"https://mp.weixin.qq.com/s/Ks7e7TPF2AujQIVbAqu_Rw\">介绍一款自动给添加不同浏览器CSS3前缀的插件~Autoprefixer（附其他前端开发插件）</a>\n",
    "\n",
    "### 通过`cssrem`自动转换px到rem\n",
    "\n",
    "这个移动布局用的比较多，使用的时候有一点需要注意一下：**需先设置默认root字体大小!**（一般设置为20px）\n",
    "\n",
    "![12.默认字体大小.jpg](https://img2018.cnblogs.com/blog/1127869/201904/1127869-20190424211635381-1053939636.jpg)\n",
    "\n",
    "PS：移动布局一般按照这个尺寸的双倍来设计：\n",
    "\n",
    "![12.尺寸.jpg](https://img2018.cnblogs.com/blog/1127869/201904/1127869-20190424211603981-1987703542.jpg)\n",
    "\n",
    "其他的没什么好说的了，一切尽在代码中了~ <https://github.com/lotapp/H5Blog/tree/master/mobil>\n",
    "\n",
    "(完)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Javascript (Node.js)",
   "language": "javascript",
   "name": "javascript"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
